From d93499cc6f7f64c050cc3536efe7bf0d5b36dd64 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 19 Nov 2019 20:16:15 +0300 Subject: [PATCH] rpc: implement CalculateInputs for RPC client Using getunspents RPC call. --- pkg/rpc/client.go | 26 ++++++++++++++++++++++++++ pkg/rpc/neoScanBalanceGetter.go | 22 +++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/pkg/rpc/client.go b/pkg/rpc/client.go index eae5d30ec..30c19ac9d 100644 --- a/pkg/rpc/client.go +++ b/pkg/rpc/client.go @@ -11,7 +11,10 @@ import ( "sync" "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/util" "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 { var ( r = request{ diff --git a/pkg/rpc/neoScanBalanceGetter.go b/pkg/rpc/neoScanBalanceGetter.go index 50d6fb289..543ca12cb 100644 --- a/pkg/rpc/neoScanBalanceGetter.go +++ b/pkg/rpc/neoScanBalanceGetter.go @@ -6,6 +6,7 @@ import ( "net/http" "sort" + "github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/rpc/wrappers" "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) { var ( err error - num, i uint16 - required = cost - selected = util.Fixed8(0) us []*Unspent assetUnspent Unspent 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) } 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 { break } @@ -81,8 +89,8 @@ func (s NeoScanServer) CalculateInputs(address string, assetIDUint util.Uint256, inputs := make([]transaction.Input, 0, num) for i = 0; i < num; i++ { inputs = append(inputs, transaction.Input{ - PrevHash: assetUnspent.Unspent[i].Tx, - PrevIndex: assetUnspent.Unspent[i].Index, + PrevHash: utxos[i].Tx, + PrevIndex: utxos[i].Index, }) }