2018-03-05 08:53:09 +00:00
|
|
|
package rpc
|
|
|
|
|
2018-12-21 09:32:18 +00:00
|
|
|
import (
|
|
|
|
"encoding/hex"
|
2019-11-20 13:07:43 +00:00
|
|
|
"fmt"
|
2018-12-21 09:32:18 +00:00
|
|
|
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
2019-11-20 13:07:43 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
2018-12-21 09:32:18 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
2018-03-25 16:21:00 +00:00
|
|
|
|
2019-09-03 15:14:19 +00:00
|
|
|
// getBlock returns a block by its hash or index/height. If verbose is true
|
2018-03-05 08:53:09 +00:00
|
|
|
// the response will contain a pretty Block object instead of the raw hex string.
|
2019-09-03 15:25:19 +00:00
|
|
|
// missing output wrapper at the moment, thus commented out
|
|
|
|
// func (c *Client) getBlock(indexOrHash interface{}, verbose bool) (*response, error) {
|
|
|
|
// var (
|
|
|
|
// params = newParams(indexOrHash)
|
|
|
|
// resp = &response{}
|
|
|
|
// )
|
|
|
|
// if verbose {
|
|
|
|
// params = newParams(indexOrHash, 1)
|
|
|
|
// }
|
|
|
|
// if err := c.performRequest("getblock", params, resp); err != nil {
|
|
|
|
// return nil, err
|
|
|
|
// }
|
|
|
|
// return resp, nil
|
|
|
|
// }
|
2018-03-05 08:53:09 +00:00
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// GetAccountState returns detailed information about a NEO account.
|
2018-03-05 08:53:09 +00:00
|
|
|
func (c *Client) GetAccountState(address string) (*AccountStateResponse, error) {
|
|
|
|
var (
|
|
|
|
params = newParams(address)
|
|
|
|
resp = &AccountStateResponse{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("getaccountstate", params, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2019-11-19 17:15:32 +00:00
|
|
|
// GetUnspents returns UTXOs for the given NEO account.
|
|
|
|
func (c *Client) GetUnspents(address string) (*UnspentResponse, error) {
|
|
|
|
var (
|
|
|
|
params = newParams(address)
|
|
|
|
resp = &UnspentResponse{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("getunspents", params, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2019-02-13 18:01:10 +00:00
|
|
|
// InvokeScript returns the result of the given script after running it true the VM.
|
|
|
|
// NOTE: This is a test invoke and will not affect the blockchain.
|
2018-03-05 08:53:09 +00:00
|
|
|
func (c *Client) InvokeScript(script string) (*InvokeScriptResponse, error) {
|
|
|
|
var (
|
|
|
|
params = newParams(script)
|
|
|
|
resp = &InvokeScriptResponse{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("invokescript", params, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// InvokeFunction returns the results after calling the smart contract scripthash
|
2018-03-25 16:21:00 +00:00
|
|
|
// with the given operation and parameters.
|
|
|
|
// NOTE: this is test invoke and will not affect the blockchain.
|
|
|
|
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter) (*InvokeScriptResponse, error) {
|
|
|
|
var (
|
|
|
|
p = newParams(script, operation, params)
|
|
|
|
resp = &InvokeScriptResponse{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("invokefunction", p, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// Invoke returns the results after calling the smart contract scripthash
|
2018-11-26 15:57:53 +00:00
|
|
|
// with the given parameters.
|
|
|
|
func (c *Client) Invoke(script string, params []smartcontract.Parameter) (*InvokeScriptResponse, error) {
|
|
|
|
var (
|
|
|
|
p = newParams(script, params)
|
|
|
|
resp = &InvokeScriptResponse{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("invoke", p, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2019-09-03 15:14:19 +00:00
|
|
|
// getRawTransaction queries a transaction by hash.
|
2019-09-03 15:25:19 +00:00
|
|
|
// missing output wrapper at the moment, thus commented out
|
|
|
|
// func (c *Client) getRawTransaction(hash string, verbose bool) (*response, error) {
|
|
|
|
// var (
|
|
|
|
// params = newParams(hash, verbose)
|
|
|
|
// resp = &response{}
|
|
|
|
// )
|
|
|
|
// if err := c.performRequest("getrawtransaction", params, resp); err != nil {
|
|
|
|
// return nil, err
|
|
|
|
// }
|
|
|
|
// return resp, nil
|
|
|
|
// }
|
2018-06-27 05:48:39 +00:00
|
|
|
|
2019-09-03 15:14:19 +00:00
|
|
|
// sendRawTransaction broadcasts a transaction over the NEO network.
|
2018-03-05 08:53:09 +00:00
|
|
|
// The given hex string needs to be signed with a keypair.
|
|
|
|
// When the result of the response object is true, the TX has successfully
|
|
|
|
// been broadcasted to the network.
|
2019-11-20 13:07:43 +00:00
|
|
|
func (c *Client) sendRawTransaction(rawTX *transaction.Transaction) (*response, error) {
|
2018-03-05 08:53:09 +00:00
|
|
|
var (
|
2019-11-20 13:07:43 +00:00
|
|
|
params = newParams(hex.EncodeToString(rawTX.Bytes()))
|
2018-03-05 08:53:09 +00:00
|
|
|
resp = &response{}
|
|
|
|
)
|
|
|
|
if err := c.performRequest("sendrawtransaction", params, resp); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return resp, nil
|
|
|
|
}
|
2018-12-21 09:32:18 +00:00
|
|
|
|
|
|
|
// SendToAddress sends an amount of specific asset to a given address.
|
2019-02-12 19:03:21 +00:00
|
|
|
// This call requires open wallet. (`wif` key in client struct.)
|
2018-12-21 09:32:18 +00:00
|
|
|
// If response.Result is `true` then transaction was formed correctly and was written in blockchain.
|
2019-01-22 12:14:40 +00:00
|
|
|
func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.Fixed8) (*SendToAddressResponse, error) {
|
2018-12-21 09:32:18 +00:00
|
|
|
var (
|
|
|
|
err error
|
|
|
|
rawTx *transaction.Transaction
|
|
|
|
txParams = ContractTxParams{
|
2019-09-03 15:11:13 +00:00
|
|
|
assetID: asset,
|
2019-01-22 12:14:40 +00:00
|
|
|
address: address,
|
|
|
|
value: amount,
|
2019-02-12 19:03:21 +00:00
|
|
|
wif: c.WIF(),
|
|
|
|
balancer: c.Balancer(),
|
2018-12-21 09:32:18 +00:00
|
|
|
}
|
2019-01-22 12:14:40 +00:00
|
|
|
resp *response
|
|
|
|
response = &SendToAddressResponse{}
|
2018-12-21 09:32:18 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if rawTx, err = CreateRawContractTransaction(txParams); err != nil {
|
2019-01-22 12:14:40 +00:00
|
|
|
return nil, errors.Wrap(err, "failed to create raw transaction for `sendtoaddress`")
|
2018-12-21 09:32:18 +00:00
|
|
|
}
|
2019-11-20 13:07:43 +00:00
|
|
|
if resp, err = c.sendRawTransaction(rawTx); err != nil {
|
2019-01-22 12:14:40 +00:00
|
|
|
return nil, errors.Wrap(err, "failed to send raw transaction")
|
|
|
|
}
|
|
|
|
response.Error = resp.Error
|
|
|
|
response.ID = resp.ID
|
|
|
|
response.JSONRPC = resp.JSONRPC
|
|
|
|
response.Result = &TxResponse{
|
2019-08-22 17:33:58 +00:00
|
|
|
TxID: rawTx.Hash().ReverseString(),
|
2019-01-22 12:14:40 +00:00
|
|
|
}
|
|
|
|
return response, nil
|
2018-12-21 09:32:18 +00:00
|
|
|
}
|
2019-11-20 13:07:43 +00:00
|
|
|
|
2019-11-29 14:59:07 +00:00
|
|
|
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
|
|
|
// transaction using given wif to sign it and spending the amount of gas
|
|
|
|
// specified. It returns a hash of the invocation transaction and an error.
|
|
|
|
func (c *Client) SignAndPushInvocationTx(script []byte, wif *keys.WIF, gas util.Fixed8) (util.Uint256, error) {
|
2019-11-20 13:07:43 +00:00
|
|
|
var txHash util.Uint256
|
2019-11-29 14:59:07 +00:00
|
|
|
var err error
|
2019-11-20 13:07:43 +00:00
|
|
|
|
|
|
|
gasIDB, _ := hex.DecodeString("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")
|
|
|
|
gasID, _ := util.Uint256DecodeReverseBytes(gasIDB)
|
|
|
|
|
2019-11-29 14:59:07 +00:00
|
|
|
tx := transaction.NewInvocationTX(script, gas)
|
2019-11-20 13:07:43 +00:00
|
|
|
|
|
|
|
fromAddress := wif.PrivateKey.Address()
|
|
|
|
|
2019-11-29 15:00:08 +00:00
|
|
|
if gas > 0 {
|
|
|
|
if err = AddInputsAndUnspentsToTx(tx, fromAddress, gasID, gas, c); err != nil {
|
|
|
|
return txHash, errors.Wrap(err, "failed to add inputs and unspents to transaction")
|
|
|
|
}
|
2019-11-20 13:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err = SignTx(tx, wif); err != nil {
|
|
|
|
return txHash, errors.Wrap(err, "failed to sign tx")
|
|
|
|
}
|
|
|
|
txHash = tx.Hash()
|
|
|
|
resp, err := c.sendRawTransaction(tx)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return txHash, errors.Wrap(err, "failed sendning tx")
|
|
|
|
}
|
|
|
|
if resp.Error != nil {
|
|
|
|
return txHash, fmt.Errorf("remote returned %d: %s", resp.Error.Code, resp.Error.Message)
|
|
|
|
}
|
|
|
|
return txHash, nil
|
|
|
|
}
|