Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

сreate bulk methods to retrieve nfts and jettons #506

Merged
merged 1 commit into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -8313,6 +8313,33 @@
]
}
},
"/v2/jettons/_bulk": {
"post": {
"description": "Get jetton metadata items by jetton master addresses",
"operationId": "getJettonInfosByAddresses",
"requestBody": {
"$ref": "#/components/requestBodies/AccountIDs"
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Jettons"
}
}
},
"description": "a list of jettons"
},
"default": {
"$ref": "#/components/responses/Error"
}
},
"tags": [
"Jettons"
]
}
},
"/v2/jettons/{account_id}": {
"get": {
"description": "Get jetton metadata by jetton master address",
Expand Down Expand Up @@ -9524,6 +9551,33 @@
]
}
},
"/v2/nfts/collections/_bulk": {
"post": {
"description": "Get NFT collection items by their addresses",
"operationId": "getNftCollectionItemsByAddresses",
"requestBody": {
"$ref": "#/components/requestBodies/AccountIDs"
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NftCollections"
}
}
},
"description": "nft collections"
},
"default": {
"$ref": "#/components/responses/Error"
}
},
"tags": [
"NFT"
]
}
},
"/v2/nfts/collections/{account_id}": {
"get": {
"description": "Get NFT collection by collection address",
Expand Down
35 changes: 34 additions & 1 deletion api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,23 @@ paths:
$ref: '#/components/schemas/NftCollection'
'default':
$ref: '#/components/responses/Error'
/v2/nfts/collections/_bulk:
post:
description: Get NFT collection items by their addresses
operationId: getNftCollectionItemsByAddresses
tags:
- NFT
requestBody:
$ref: "#/components/requestBodies/AccountIDs"
responses:
'200':
description: nft collections
content:
application/json:
schema:
$ref: '#/components/schemas/NftCollections'
'default':
$ref: '#/components/responses/Error'
/v2/nfts/collections/{account_id}/items:
get:
description: Get NFT items from collection by collection address
Expand Down Expand Up @@ -1538,6 +1555,23 @@ paths:
$ref: '#/components/schemas/JettonInfo'
'default':
$ref: '#/components/responses/Error'
/v2/jettons/_bulk:
post:
description: Get jetton metadata items by jetton master addresses
operationId: getJettonInfosByAddresses
tags:
- Jettons
requestBody:
$ref: "#/components/requestBodies/AccountIDs"
responses:
'200':
description: a list of jettons
content:
application/json:
schema:
$ref: '#/components/schemas/Jettons'
'default':
$ref: '#/components/responses/Error'
/v2/jettons/{account_id}/holders:
get:
description: Get jetton's holders
Expand Down Expand Up @@ -6848,7 +6882,6 @@ components:
decimals:
type: integer
example: 9

Jettons:
type: object
required:
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type storage interface {
GetNFTs(ctx context.Context, accounts []tongo.AccountID) ([]core.NftItem, error)
SearchNFTs(ctx context.Context, collection *core.Filter[tongo.AccountID], owner *core.Filter[tongo.AccountID], includeOnSale bool, onlyVerified bool, limit, offset int) ([]tongo.AccountID, error)
GetNftCollections(ctx context.Context, limit, offset *int32) ([]core.NftCollection, error)
GetNftCollectionsByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.NftCollection, error)
GetNftCollectionByCollectionAddress(ctx context.Context, address tongo.AccountID) (core.NftCollection, error)
GetAccountNftsHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT *int64, startTime *int64, endTime *int64) ([]tongo.Bits256, error)
GetNftHistory(ctx context.Context, address tongo.AccountID, limit int, beforeLT *int64, startTime *int64, endTime *int64) ([]tongo.Bits256, error)
Expand All @@ -85,6 +86,7 @@ type storage interface {
GetWalletPubKey(ctx context.Context, address tongo.AccountID) (ed25519.PublicKey, error)
GetSubscriptions(ctx context.Context, address tongo.AccountID) ([]core.Subscription, error)
GetJettonMasters(ctx context.Context, limit, offset int) ([]core.JettonMaster, error)
GetJettonMastersByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.JettonMaster, error)

GetLastConfig(ctx context.Context) (ton.BlockchainConfig, error)
GetConfigRaw(ctx context.Context) ([]byte, error)
Expand Down
13 changes: 13 additions & 0 deletions pkg/api/jetton_converters.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,16 @@ func (h *Handler) convertJettonBalance(ctx context.Context, wallet core.JettonWa

return jettonBalance, nil
}

func (h *Handler) convertJettonInfo(ctx context.Context, master core.JettonMaster, holders map[tongo.AccountID]int32) oas.JettonInfo {
meta := h.GetJettonNormalizedMetadata(ctx, master.Address)
metadata := jettonMetadata(master.Address, meta)
return oas.JettonInfo{
Mintable: master.Mintable,
TotalSupply: master.TotalSupply.String(),
Metadata: metadata,
Verification: oas.JettonVerificationType(meta.Verification),
HoldersCount: holders[master.Address],
Admin: convertOptAccountAddress(master.Admin, h.addressBook),
}
}
49 changes: 38 additions & 11 deletions pkg/api/jetton_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,13 @@ func (h *Handler) GetJettons(ctx context.Context, params oas.GetJettonsParams) (
for idx, jetton := range jettons {
addresses[idx] = jetton.Address
}
jettonsHolders, err := h.storage.GetJettonsHoldersCount(ctx, addresses)
holders, err := h.storage.GetJettonsHoldersCount(ctx, addresses)
if err != nil {
return nil, toError(http.StatusInternalServerError, err)
}
results := make([]oas.JettonInfo, len(jettons))
for idx, master := range jettons {
meta := h.GetJettonNormalizedMetadata(ctx, master.Address)
metadata := jettonMetadata(master.Address, meta)
results[idx] = oas.JettonInfo{
Mintable: master.Mintable,
TotalSupply: master.TotalSupply.String(),
Metadata: metadata,
Verification: oas.JettonVerificationType(meta.Verification),
HoldersCount: jettonsHolders[master.Address],
Admin: convertOptAccountAddress(master.Admin, h.addressBook),
}
results[idx] = h.convertJettonInfo(ctx, master, holders)
}
return &oas.Jettons{Jettons: results}, nil
}
Expand Down Expand Up @@ -271,3 +262,39 @@ func (h *Handler) GetJettonTransferPayload(ctx context.Context, params oas.GetJe
}
return &res, nil
}

func (h Handler) GetJettonInfosByAddresses(ctx context.Context, request oas.OptGetJettonInfosByAddressesReq) (*oas.Jettons, error) {
if len(request.Value.AccountIds) == 0 {
return nil, toError(http.StatusBadRequest, fmt.Errorf("empty list of ids"))
}
if !h.limits.isBulkQuantityAllowed(len(request.Value.AccountIds)) {
return nil, toError(http.StatusBadRequest, fmt.Errorf("the maximum number of addresses to request at once: %v", h.limits.BulkLimits))
}
accounts := make([]ton.AccountID, len(request.Value.AccountIds))
var err error
for i := range request.Value.AccountIds {
account, err := tongo.ParseAddress(request.Value.AccountIds[i])
if err != nil {
return nil, toError(http.StatusBadRequest, err)
}
accounts[i] = account.ID
}
jettons, err := h.storage.GetJettonMastersByAddresses(ctx, accounts)
if err != nil {
return nil, toError(http.StatusInternalServerError, err)
}
addresses := make([]tongo.AccountID, len(jettons))
for idx, jetton := range jettons {
addresses[idx] = jetton.Address
}
jettonsHolders, err := h.storage.GetJettonsHoldersCount(ctx, addresses)
if err != nil {
return nil, toError(http.StatusInternalServerError, err)
}
results := make([]oas.JettonInfo, len(jettons))
for idx, master := range jettons {
results[idx] = h.convertJettonInfo(ctx, master, jettonsHolders)
}

return &oas.Jettons{Jettons: results}, nil
}
33 changes: 32 additions & 1 deletion pkg/api/nft_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"context"
"errors"
"fmt"
"go.uber.org/zap"
"net/http"

"go.uber.org/zap"

"golang.org/x/exp/slices"

"github.com/tonkeeper/opentonapi/pkg/core"
Expand Down Expand Up @@ -175,3 +176,33 @@ func (h *Handler) GetNftHistoryByID(ctx context.Context, params oas.GetNftHistor
}
return &oas.AccountEvents{Events: events, NextFrom: lastLT}, nil
}

func (h *Handler) GetNftCollectionItemsByAddresses(ctx context.Context, request oas.OptGetNftCollectionItemsByAddressesReq) (*oas.NftCollections, error) {
if len(request.Value.AccountIds) == 0 {
return nil, toError(http.StatusBadRequest, fmt.Errorf("empty list of ids"))
}
if !h.limits.isBulkQuantityAllowed(len(request.Value.AccountIds)) {
return nil, toError(http.StatusBadRequest, fmt.Errorf("the maximum number of addresses to request at once: %v", h.limits.BulkLimits))
}
accounts := make([]tongo.AccountID, len(request.Value.AccountIds))
var err error
for i := range request.Value.AccountIds {
account, err := tongo.ParseAddress(request.Value.AccountIds[i])
if err != nil {
return nil, toError(http.StatusBadRequest, err)
}
accounts[i] = account.ID
}
collections, err := h.storage.GetNftCollectionsByAddresses(ctx, accounts)
if errors.Is(err, core.ErrEntityNotFound) {
return nil, toError(http.StatusNotFound, err)
}
if err != nil {
return nil, toError(http.StatusInternalServerError, err)
}
var result oas.NftCollections
for _, i := range collections {
result.NftCollections = append(result.NftCollections, convertNftCollection(i, h.addressBook))
}
return &result, nil
}
6 changes: 5 additions & 1 deletion pkg/litestorage/jetton.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ func (s *LiteStorage) JettonMastersForWallets(ctx context.Context, wallets []ton

func (s *LiteStorage) GetJettonMasters(ctx context.Context, limit, offset int) ([]core.JettonMaster, error) {
// TODO: implement
return nil, nil
return []core.JettonMaster{}, nil
}

func (s *LiteStorage) GetJettonMastersByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.JettonMaster, error) {
return []core.JettonMaster{}, nil
}

func (s *LiteStorage) GetJettonsHoldersCount(ctx context.Context, accountIDs []tongo.AccountID) (map[tongo.AccountID]int32, error) {
Expand Down
7 changes: 6 additions & 1 deletion pkg/litestorage/nft.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/tonkeeper/tongo/abi"
"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/tep64"
"github.com/tonkeeper/tongo/ton"
)

func (s *LiteStorage) GetNFTs(ctx context.Context, accounts []tongo.AccountID) ([]core.NftItem, error) {
Expand All @@ -30,7 +31,11 @@ func (s *LiteStorage) SearchNFTs(ctx context.Context,
}

func (s *LiteStorage) GetNftCollections(ctx context.Context, limit, offset *int32) ([]core.NftCollection, error) {
return nil, nil
return []core.NftCollection{}, nil
}

func (s *LiteStorage) GetNftCollectionsByAddresses(ctx context.Context, addresses []ton.AccountID) ([]core.NftCollection, error) {
return []core.NftCollection{}, nil
}

func (s *LiteStorage) GetNftCollectionByCollectionAddress(ctx context.Context, address tongo.AccountID) (core.NftCollection, error) {
Expand Down
Loading
Loading