rpc: implement CalculateInputs for RPC client

Using getunspents RPC call.
This commit is contained in:
Roman Khimov 2019-11-19 20:16:15 +03:00
parent 826a29cc98
commit d93499cc6f
2 changed files with 41 additions and 7 deletions

View file

@ -11,7 +11,10 @@ import (
"sync" "sync"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/keys" "github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -152,6 +155,29 @@ func (c *Client) SetClient(cli *http.Client) {
} }
} }
// CalculateInputs creates input transactions for the specified amount of given
// asset belonging to specified address. This implementation uses GetUnspents
// JSON-RPC call internally, so make sure your RPC server suppors that.
func (c *Client) CalculateInputs(address string, asset util.Uint256, cost util.Fixed8) ([]transaction.Input, util.Fixed8, error) {
var utxos core.UnspentBalances
resp, err := c.GetUnspents(address)
if err != nil || resp.Error != nil {
if err == nil {
err = fmt.Errorf("remote returned %d: %s", resp.Error.Code, resp.Error.Message)
}
return nil, util.Fixed8(0), errors.Wrapf(err, "cannot get balance for address %v", address)
}
for _, ubi := range resp.Result.Balance {
if asset.Equals(ubi.AssetHash) {
utxos = ubi.Unspents
break
}
}
return unspentsToInputs(utxos, cost)
}
func (c *Client) performRequest(method string, p params, v interface{}) error { func (c *Client) performRequest(method string, p params, v interface{}) error {
var ( var (
r = request{ r = request{

View file

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"sort" "sort"
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/rpc/wrappers" "github.com/CityOfZion/neo-go/pkg/rpc/wrappers"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
@ -54,9 +55,6 @@ func filterSpecificAsset(asset string, balance []*Unspent, assetBalance *Unspent
func (s NeoScanServer) CalculateInputs(address string, assetIDUint util.Uint256, cost util.Fixed8) ([]transaction.Input, util.Fixed8, error) { func (s NeoScanServer) CalculateInputs(address string, assetIDUint util.Uint256, cost util.Fixed8) ([]transaction.Input, util.Fixed8, error) {
var ( var (
err error err error
num, i uint16
required = cost
selected = util.Fixed8(0)
us []*Unspent us []*Unspent
assetUnspent Unspent assetUnspent Unspent
assetID = wrappers.GlobalAssets[assetIDUint.ReverseString()] assetID = wrappers.GlobalAssets[assetIDUint.ReverseString()]
@ -65,9 +63,19 @@ func (s NeoScanServer) CalculateInputs(address string, assetIDUint util.Uint256,
return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address) return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address)
} }
filterSpecificAsset(assetID, us, &assetUnspent) filterSpecificAsset(assetID, us, &assetUnspent)
sort.Sort(assetUnspent.Unspent) return unspentsToInputs(assetUnspent.Unspent, cost)
}
for _, us := range assetUnspent.Unspent { // unspentsToInputs uses UnspentBalances to create a slice of inputs for a new
// transcation containing the required amount of asset.
func unspentsToInputs(utxos core.UnspentBalances, required util.Fixed8) ([]transaction.Input, util.Fixed8, error) {
var (
num, i uint16
selected = util.Fixed8(0)
)
sort.Sort(utxos)
for _, us := range utxos {
if selected >= required { if selected >= required {
break break
} }
@ -81,8 +89,8 @@ func (s NeoScanServer) CalculateInputs(address string, assetIDUint util.Uint256,
inputs := make([]transaction.Input, 0, num) inputs := make([]transaction.Input, 0, num)
for i = 0; i < num; i++ { for i = 0; i < num; i++ {
inputs = append(inputs, transaction.Input{ inputs = append(inputs, transaction.Input{
PrevHash: assetUnspent.Unspent[i].Tx, PrevHash: utxos[i].Tx,
PrevIndex: assetUnspent.Unspent[i].Index, PrevIndex: utxos[i].Index,
}) })
} }