rpc: implement getunclaimed

closes #712
This commit is contained in:
Anna Shaleva 2020-03-06 20:38:17 +03:00
parent aab7dd515f
commit c23a522d25
5 changed files with 139 additions and 33 deletions

View file

@ -30,41 +30,40 @@ which would yield the response:
} }
} }
``` ```
### Supported methods ### Supported methods
| Method | Implemented | | Method |
| ------- | ------------| | ------- |
| `getaccountstate` | Yes | | `getaccountstate` |
| `getapplicationlog` | Yes | | `getapplicationlog` |
| `getassetstate` | Yes | | `getassetstate` |
| `getbestblockhash` | Yes | | `getbestblockhash` |
| `getblock` | Yes | | `getblock` |
| `getblockcount` | Yes | | `getblockcount` |
| `getblockhash` | Yes | | `getblockhash` |
| `getblockheader` | Yes | | `getblockheader` |
| `getblocksysfee` | Yes | | `getblocksysfee` |
| `getclaimable` | Yes | | `getclaimable` |
| `getconnectioncount` | Yes | | `getconnectioncount` |
| `getcontractstate` | Yes | | `getcontractstate` |
| `getnep5balances` | Yes | | `getnep5balances` |
| `getnep5transfers` | Yes | | `getnep5transfers` |
| `getpeers` | Yes | | `getpeers` |
| `getrawmempool` | Yes | | `getrawmempool` |
| `getrawtransaction` | Yes | | `getrawtransaction` |
| `getstorage` | Yes | | `getstorage` |
| `gettransactionheight` | Yes | | `gettransactionheight` |
| `gettxout` | Yes | | `gettxout` |
| `getunclaimed` | No (#712) | | `getunclaimed` |
| `getunspents` | Yes | | `getunspents` |
| `getvalidators` | Yes | | `getvalidators` |
| `getversion` | Yes | | `getversion` |
| `invoke` | Yes | | `invoke` |
| `invokefunction` | Yes | | `invokefunction` |
| `invokescript` | Yes | | `invokescript` |
| `sendrawtransaction` | Yes | | `sendrawtransaction` |
| `submitblock` | Yes | | `submitblock` |
| `validateaddress` | Yes | | `validateaddress` |
### Unsupported methods ### Unsupported methods

View file

@ -0,0 +1,49 @@
package result
import (
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// Unclaimed wrapper is used to represent getunclaimed return result.
type Unclaimed struct {
Available util.Fixed8 `json:"available"`
Unavailable util.Fixed8 `json:"unavailable"`
Unclaimed util.Fixed8 `json:"unclaimed"`
}
// NewUnclaimed creates a new Unclaimed wrapper using given Blockchainer.
func NewUnclaimed(a *state.Account, chain core.Blockchainer) (*Unclaimed, error) {
var (
available util.Fixed8
unavailable util.Fixed8
)
for _, ucb := range a.Unclaimed {
gen, sys, err := chain.CalculateClaimable(ucb.Value, ucb.Start, ucb.End)
if err != nil {
return nil, err
}
available += gen + sys
}
blockHeight := chain.BlockHeight()
for _, usb := range a.Balances[core.GoverningTokenID()] {
_, txHeight, err := chain.GetTransaction(usb.Tx)
if err != nil {
return nil, err
}
gen, sys, err := chain.CalculateClaimable(usb.Value, txHeight, blockHeight)
if err != nil {
return nil, err
}
unavailable += gen + sys
}
return &Unclaimed{
Available: available,
Unavailable: unavailable,
Unclaimed: available + unavailable,
}, nil
}

View file

@ -178,6 +178,14 @@ var (
}, },
) )
getunclaimedCalled = prometheus.NewCounter(
prometheus.CounterOpts{
Help: "Number of calls to getunclaimed rpc endpoint",
Name: "getunclaimed_called",
Namespace: "neogo",
},
)
getunspentsCalled = prometheus.NewCounter( getunspentsCalled = prometheus.NewCounter(
prometheus.CounterOpts{ prometheus.CounterOpts{
Help: "Number of calls to getunspents rpc endpoint", Help: "Number of calls to getunspents rpc endpoint",
@ -229,6 +237,7 @@ func init() {
validateaddressCalled, validateaddressCalled,
getassetstateCalled, getassetstateCalled,
getaccountstateCalled, getaccountstateCalled,
getunclaimedCalled,
getunspentsCalled, getunspentsCalled,
gettransactionheightCalled, gettransactionheightCalled,
gettxoutCalled, gettxoutCalled,

View file

@ -298,6 +298,10 @@ Methods:
gettxoutCalled.Inc() gettxoutCalled.Inc()
results, resultsErr = s.getTxOut(reqParams) results, resultsErr = s.getTxOut(reqParams)
case "getunclaimed":
getunclaimedCalled.Inc()
results, resultsErr = s.getUnclaimed(reqParams)
case "getunspents": case "getunspents":
getunspentsCalled.Inc() getunspentsCalled.Inc()
results, resultsErr = s.getAccountState(reqParams, true) results, resultsErr = s.getAccountState(reqParams, true)
@ -768,6 +772,25 @@ func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, error) {
return hex.EncodeToString(buf.Bytes()), nil return hex.EncodeToString(buf.Bytes()), nil
} }
// getUnclaimed returns unclaimed GAS amount of the specified address.
func (s *Server) getUnclaimed(ps request.Params) (interface{}, error) {
p, ok := ps.ValueWithType(0, request.StringT)
if !ok {
return nil, response.ErrInvalidParams
}
u, err := p.GetUint160FromAddress()
if err != nil {
return nil, response.ErrInvalidParams
}
acc := s.chain.GetAccountState(u)
if acc == nil {
return nil, response.NewInternalServerError("unknown account", nil)
}
return result.NewUnclaimed(acc, s.chain)
}
// getValidators returns the current NEO consensus nodes information and voting status. // getValidators returns the current NEO consensus nodes information and voting status.
func (s *Server) getValidators() (interface{}, error) { func (s *Server) getValidators() (interface{}, error) {
var validators keys.PublicKeys var validators keys.PublicKeys

View file

@ -601,6 +601,32 @@ var rpcTestCases = map[string][]rpcTestCase{
fail: true, fail: true,
}, },
}, },
"getunclaimed": {
{
name: "no params",
params: "[]",
fail: true,
},
{
name: "invalid address",
params: `["invalid"]`,
fail: true,
},
{
name: "positive",
params: `["AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU"]`,
result: func(*executor) interface{} {
return &result.Unclaimed{}
},
check: func(t *testing.T, e *executor, uncl interface{}) {
res, ok := uncl.(*result.Unclaimed)
require.True(t, ok)
assert.Equal(t, res.Available, util.Fixed8FromInt64(8))
assert.True(t, res.Unavailable > 0)
assert.Equal(t, res.Available + res.Unavailable, res.Unclaimed)
},
},
},
"getunspents": { "getunspents": {
{ {
name: "positive", name: "positive",