Skip to content

Commit

Permalink
new endpoints for esdt, sft and nft
Browse files Browse the repository at this point in the history
  • Loading branch information
bogdan-rosianu committed May 4, 2021
1 parent 29097cd commit 2f05d47
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 48 deletions.
7 changes: 4 additions & 3 deletions api/mock/facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type Facade struct {
GetBlockByHashCalled func(hash string, withTxs bool) (*api.Block, error)
GetBlockByNonceCalled func(nonce uint64, withTxs bool) (*api.Block, error)
GetTotalStakedValueHandler func() (*api.StakeValues, error)
GetAllIssuedESDTsCalled func() ([]string, error)
GetAllIssuedESDTsCalled func(tokenType string) ([]string, error)
GetDirectStakedListHandler func() ([]*api.DirectStakedValue, error)
GetDelegatorsListHandler func() ([]*api.Delegator, error)
}
Expand Down Expand Up @@ -145,10 +145,11 @@ func (f *Facade) GetAllESDTTokens(address string) (map[string]*esdt.ESDigitalTok
}

// GetAllIssuedESDTs -
func (f *Facade) GetAllIssuedESDTs() ([]string, error) {
func (f *Facade) GetAllIssuedESDTs(tokenType string) ([]string, error) {
if f.GetAllIssuedESDTsCalled != nil {
return f.GetAllIssuedESDTsCalled()
return f.GetAllIssuedESDTsCalled(tokenType)
}

return make([]string, 0), nil
}

Expand Down
55 changes: 31 additions & 24 deletions api/network/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const (
getStatusPath = "/status"
economicsPath = "/economics"
getESDTsPath = "/esdts"
getFFTsPath = "/esdt/fungible-tokens"
getSFTsPath = "/esdt/semi-fungible-tokens"
getNFTsPath = "/esdt/non-fungible-tokens"
directStakedInfoPath = "/direct-staked-info"
delegatedInfoPath = "/delegated-info"
)
Expand All @@ -27,7 +30,7 @@ type FacadeHandler interface {
GetDirectStakedList() ([]*api.DirectStakedValue, error)
GetDelegatorsList() ([]*api.Delegator, error)
StatusMetrics() external.StatusMetricsHandler
GetAllIssuedESDTs() ([]string, error)
GetAllIssuedESDTs(tokenType string) ([]string, error)
IsInterfaceNil() bool
}

Expand All @@ -36,7 +39,10 @@ func Routes(router *wrapper.RouterWrapper) {
router.RegisterHandler(http.MethodGet, getConfigPath, GetNetworkConfig)
router.RegisterHandler(http.MethodGet, getStatusPath, GetNetworkStatus)
router.RegisterHandler(http.MethodGet, economicsPath, EconomicsMetrics)
router.RegisterHandler(http.MethodGet, getESDTsPath, GetAllIssuedESDTs)
router.RegisterHandler(http.MethodGet, getESDTsPath, getHandlerFuncForEsdt(""))
router.RegisterHandler(http.MethodGet, getFFTsPath, getHandlerFuncForEsdt(core.FungibleESDT))
router.RegisterHandler(http.MethodGet, getSFTsPath, getHandlerFuncForEsdt(core.SemiFungibleESDT))
router.RegisterHandler(http.MethodGet, getNFTsPath, getHandlerFuncForEsdt(core.NonFungibleESDT))
router.RegisterHandler(http.MethodGet, directStakedInfoPath, DirectStakedInfo)
router.RegisterHandler(http.MethodGet, delegatedInfoPath, DelegatedInfo)
}
Expand Down Expand Up @@ -141,34 +147,35 @@ func EconomicsMetrics(c *gin.Context) {
)
}

// GetAllIssuedESDTs returns all the issued esdts from the metachain
func GetAllIssuedESDTs(c *gin.Context) {
facade, ok := getFacade(c)
if !ok {
return
}
func getHandlerFuncForEsdt(tokenType string) func(c *gin.Context) {
return func(c *gin.Context) {
facade, ok := getFacade(c)
if !ok {
return
}

tokens, err := facade.GetAllIssuedESDTs(tokenType)
if err != nil {
c.JSON(
http.StatusInternalServerError,
shared.GenericAPIResponse{
Data: nil,
Error: err.Error(),
Code: shared.ReturnCodeInternalError,
},
)
return
}

tokens, err := facade.GetAllIssuedESDTs()
if err != nil {
c.JSON(
http.StatusInternalServerError,
http.StatusOK,
shared.GenericAPIResponse{
Data: nil,
Error: err.Error(),
Code: shared.ReturnCodeInternalError,
Data: gin.H{"tokens": tokens},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
return
}

c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"tokens": tokens},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

// DirectStakedInfo is the endpoint that will return the directed staked info list
Expand Down
4 changes: 2 additions & 2 deletions api/network/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func TestEconomicsMetrics_CannotGetStakeValues(t *testing.T) {
func TestGetAllIssuedESDTs_ShouldWork(t *testing.T) {
tokens := []string{"tokenA", "tokenB"}
facade := mock.Facade{
GetAllIssuedESDTsCalled: func() ([]string, error) {
GetAllIssuedESDTsCalled: func(_ string) ([]string, error) {
return tokens, nil
},
}
Expand All @@ -239,7 +239,7 @@ func TestGetAllIssuedESDTs_ShouldWork(t *testing.T) {
func TestGetAllIssuedESDTs_Error(t *testing.T) {
localErr := fmt.Errorf("%s", "local error")
facade := mock.Facade{
GetAllIssuedESDTsCalled: func() ([]string, error) {
GetAllIssuedESDTsCalled: func(_ string) ([]string, error) {
return nil, localErr
},
}
Expand Down
2 changes: 1 addition & 1 deletion facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type NodeHandler interface {
GetKeyValuePairs(address string) (map[string]string, error)

// GetAllIssuedESDTs returns all the issued esdt tokens from esdt system smart contract
GetAllIssuedESDTs() ([]string, error)
GetAllIssuedESDTs(tokenType string) ([]string, error)

// GetESDTData returns the esdt data from a given account, given key and given nonce
GetESDTData(address, tokenID string, nonce uint64) (*esdt.ESDigitalToken, error)
Expand Down
6 changes: 3 additions & 3 deletions facade/mock/nodeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type NodeStub struct {
GetESDTDataCalled func(address string, key string, nonce uint64) (*esdt.ESDigitalToken, error)
GetAllESDTTokensCalled func(address string) (map[string]*esdt.ESDigitalToken, error)
GetKeyValuePairsCalled func(address string) (map[string]string, error)
GetAllIssuedESDTsCalled func() ([]string, error)
GetAllIssuedESDTsCalled func(tokenType string) ([]string, error)
}

// GetUsername -
Expand Down Expand Up @@ -202,9 +202,9 @@ func (ns *NodeStub) GetAllESDTTokens(address string) (map[string]*esdt.ESDigital
}

// GetAllIssuedESDTs -
func (ns *NodeStub) GetAllIssuedESDTs() ([]string, error) {
func (ns *NodeStub) GetAllIssuedESDTs(tokenType string) ([]string, error) {
if ns.GetAllIssuedESDTsCalled != nil {
return ns.GetAllIssuedESDTsCalled()
return ns.GetAllIssuedESDTsCalled(tokenType)
}
return make([]string, 0), nil
}
Expand Down
4 changes: 2 additions & 2 deletions facade/nodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ func (nf *nodeFacade) GetAllESDTTokens(address string) (map[string]*esdt.ESDigit
}

// GetAllIssuedESDTs returns all the issued esdts from the esdt system smart contract
func (nf *nodeFacade) GetAllIssuedESDTs() ([]string, error) {
return nf.node.GetAllIssuedESDTs()
func (nf *nodeFacade) GetAllIssuedESDTs(tokenType string) ([]string, error) {
return nf.node.GetAllIssuedESDTs(tokenType)
}

// CreateTransaction creates a transaction from all needed fields
Expand Down
8 changes: 4 additions & 4 deletions facade/nodeFacade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,14 +740,14 @@ func TestNodeFacade_GetAllIssuedESDTs(t *testing.T) {
expectedValue := []string{"value"}
arg := createMockArguments()
arg.Node = &mock.NodeStub{
GetAllIssuedESDTsCalled: func() ([]string, error) {
GetAllIssuedESDTsCalled: func(_ string) ([]string, error) {
return expectedValue, nil
},
}

nf, _ := NewNodeFacade(arg)

res, err := nf.GetAllIssuedESDTs()
res, err := nf.GetAllIssuedESDTs("")
assert.NoError(t, err)
assert.Equal(t, expectedValue, res)
}
Expand All @@ -758,14 +758,14 @@ func TestNodeFacade_GetAllIssuedESDTsWithError(t *testing.T) {
localErr := errors.New("local")
arg := createMockArguments()
arg.Node = &mock.NodeStub{
GetAllIssuedESDTsCalled: func() ([]string, error) {
GetAllIssuedESDTsCalled: func(_ string) ([]string, error) {
return nil, localErr
},
}

nf, _ := NewNodeFacade(arg)

_, err := nf.GetAllIssuedESDTs()
_, err := nf.GetAllIssuedESDTs("")
assert.Equal(t, err, localErr)
}

Expand Down
35 changes: 30 additions & 5 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import (
"github.com/ElrondNetwork/elrond-go/statusHandler"
"github.com/ElrondNetwork/elrond-go/update"
"github.com/ElrondNetwork/elrond-go/vm"
"github.com/ElrondNetwork/elrond-go/vm/systemSmartContracts"
)

const (
Expand Down Expand Up @@ -452,7 +453,7 @@ func (n *Node) GetUsername(address string) (string, error) {
}

// GetAllIssuedESDTs returns all the issued esdt tokens, works only on metachain
func (n *Node) GetAllIssuedESDTs() ([]string, error) {
func (n *Node) GetAllIssuedESDTs(tokenType string) ([]string, error) {
account, err := n.getAccountHandlerForPubKey(vm.ESDTSCAddress)
if err != nil {
return nil, err
Expand Down Expand Up @@ -480,9 +481,33 @@ func (n *Node) GetAllIssuedESDTs() ([]string, error) {
}

for leaf := range chLeaves {
key := string(leaf.Key())
if strings.Contains(key, "-") {
tokens = append(tokens, key)
tokenName := string(leaf.Key())
if !strings.Contains(tokenName, "-") {
continue
}

if tokenType == "" {
tokens = append(tokens, tokenName)
continue
}

esdtToken := &systemSmartContracts.ESDTData{}
suffix := append(leaf.Key(), userAccount.AddressBytes()...)
value, errVal := leaf.ValueWithoutSuffix(suffix)
if errVal != nil {
log.Warn("cannot get value without suffix", "error", errVal, "key", leaf.Key())
continue
}

err = n.internalMarshalizer.Unmarshal(esdtToken, value)
if err != nil {
log.Warn("cannot unmarshal", "token name", tokenName, "err", err)
continue
}

expectedTokenType := []byte(tokenType)
if bytes.Equal(esdtToken.TokenType, expectedTokenType) {
tokens = append(tokens, tokenName)
}
}

Expand Down Expand Up @@ -591,7 +616,7 @@ func (n *Node) GetESDTData(address, tokenID string, nonce uint64) (*esdt.ESDigit
return esdtToken, nil
}

// GetAllESDTTokens returns the value of a key from a given account
// GetAllESDTTokens returns all the ESDTs that the given address interacted with
func (n *Node) GetAllESDTTokens(address string) (map[string]*esdt.ESDigitalToken, error) {
account, err := n.getAccountHandlerAPIAccounts(address)
if err != nil {
Expand Down
41 changes: 37 additions & 4 deletions node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/ElrondNetwork/elrond-go/sharding"
"github.com/ElrondNetwork/elrond-go/storage"
"github.com/ElrondNetwork/elrond-go/testscommon"
"github.com/ElrondNetwork/elrond-go/vm/systemSmartContracts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -489,20 +490,38 @@ func TestNode_GetAllESDTTokensShouldReturnEsdtAndFormattedNft(t *testing.T) {
func TestNode_GetAllIssuedESDTs(t *testing.T) {
acc, _ := state.NewUserAccount([]byte("newaddress"))
esdtToken := []byte("TCK-RANDOM")
sftToken := []byte("SFT-RANDOM")
nftToken := []byte("NFT-RANDOM")

esdtData := &esdt.ESDigitalToken{Value: big.NewInt(10)}
esdtData := &systemSmartContracts.ESDTData{TokenName: []byte("fungible"), TokenType: []byte(core.FungibleESDT)}
marshalledData, _ := getMarshalizer().Marshal(esdtData)
_ = acc.DataTrieTracker().SaveKeyValue(esdtToken, marshalledData)

suffix := append(esdtToken, acc.AddressBytes()...)
sftData := &systemSmartContracts.ESDTData{TokenName: []byte("semi fungible"), TokenType: []byte(core.SemiFungibleESDT)}
sftMarshalledData, _ := getMarshalizer().Marshal(sftData)
_ = acc.DataTrieTracker().SaveKeyValue(sftToken, sftMarshalledData)

nftData := &systemSmartContracts.ESDTData{TokenName: []byte("non fungible"), TokenType: []byte(core.NonFungibleESDT)}
nftMarshalledData, _ := getMarshalizer().Marshal(nftData)
_ = acc.DataTrieTracker().SaveKeyValue(nftToken, nftMarshalledData)

esdtSuffix := append(esdtToken, acc.AddressBytes()...)
nftSuffix := append(nftToken, acc.AddressBytes()...)
sftSuffix := append(sftToken, acc.AddressBytes()...)

acc.DataTrieTracker().SetDataTrie(
&mock.TrieStub{
GetAllLeavesOnChannelCalled: func(rootHash []byte) (chan core.KeyValueHolder, error) {
ch := make(chan core.KeyValueHolder)

go func() {
trieLeaf := keyValStorage.NewKeyValStorage(esdtToken, append(marshalledData, suffix...))
trieLeaf := keyValStorage.NewKeyValStorage(esdtToken, append(marshalledData, esdtSuffix...))
ch <- trieLeaf

trieLeaf = keyValStorage.NewKeyValStorage(sftToken, append(sftMarshalledData, sftSuffix...))
ch <- trieLeaf

trieLeaf = keyValStorage.NewKeyValStorage(nftToken, append(nftMarshalledData, nftSuffix...))
ch <- trieLeaf
close(ch)
}()
Expand Down Expand Up @@ -532,10 +551,24 @@ func TestNode_GetAllIssuedESDTs(t *testing.T) {
}}),
)

value, err := n.GetAllIssuedESDTs()
value, err := n.GetAllIssuedESDTs(core.FungibleESDT)
assert.Nil(t, err)
assert.Equal(t, 1, len(value))
assert.Equal(t, string(esdtToken), value[0])

value, err = n.GetAllIssuedESDTs(core.SemiFungibleESDT)
assert.Nil(t, err)
assert.Equal(t, 1, len(value))
assert.Equal(t, string(sftToken), value[0])

value, err = n.GetAllIssuedESDTs(core.NonFungibleESDT)
assert.Nil(t, err)
assert.Equal(t, 1, len(value))
assert.Equal(t, string(nftToken), value[0])

value, err = n.GetAllIssuedESDTs("")
assert.Nil(t, err)
assert.Equal(t, 3, len(value))
}

//------- GenerateTransaction
Expand Down

0 comments on commit 2f05d47

Please sign in to comment.