aboutsummaryrefslogtreecommitdiff
path: root/plugin/evm/client.go
diff options
context:
space:
mode:
authoraaronbuchwald <[email protected]>2020-11-25 11:28:48 -0500
committerGitHub <[email protected]>2020-11-25 11:28:48 -0500
commit2ea6c2aeacd37f347c5794d6b300a6d1815c251b (patch)
treece38ae6325561029628e09929615e141e7f3b144 /plugin/evm/client.go
parent44c27ae8f05bb7f1076d9159d4106afd41e2e010 (diff)
parent61479754d935e36993f7144d70d7c518cdb26a36 (diff)
Merge pull request #61 from ava-labs/client-api
Add avax API client and upgrade to avalanchego v1.0.5-client
Diffstat (limited to 'plugin/evm/client.go')
-rw-r--r--plugin/evm/client.go174
1 files changed, 174 insertions, 0 deletions
diff --git a/plugin/evm/client.go b/plugin/evm/client.go
new file mode 100644
index 0000000..0817545
--- /dev/null
+++ b/plugin/evm/client.go
@@ -0,0 +1,174 @@
+// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+package evm
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/ava-labs/avalanchego/api"
+ "github.com/ava-labs/avalanchego/ids"
+ "github.com/ava-labs/avalanchego/utils/formatting"
+ cjson "github.com/ava-labs/avalanchego/utils/json"
+ "github.com/ava-labs/avalanchego/utils/rpc"
+)
+
+// Client ...
+type Client struct {
+ requester rpc.EndpointRequester
+}
+
+// NewClient returns a Client for interacting with EVM [chain]
+func NewClient(uri, chain string, requestTimeout time.Duration) *Client {
+ return &Client{
+ requester: rpc.NewEndpointRequester(uri, fmt.Sprintf("/ext/bc/%s/avax", chain), "avax", requestTimeout),
+ }
+}
+
+// NewCChainClient returns a Client for interacting with the C Chain
+func NewCChainClient(uri string, requestTimeout time.Duration) *Client {
+ return NewClient(uri, "C", requestTimeout)
+}
+
+// IssueTx issues a transaction to a node and returns the TxID
+func (c *Client) IssueTx(txBytes []byte) (ids.ID, error) {
+ res := &api.JSONTxID{}
+ txStr, err := formatting.Encode(formatting.Hex, txBytes)
+ if err != nil {
+ return res.TxID, fmt.Errorf("problem hex encoding bytes: %w", err)
+ }
+ err = c.requester.SendRequest("issueTx", &api.FormattedTx{
+ Tx: txStr,
+ Encoding: formatting.Hex,
+ }, res)
+ return res.TxID, err
+}
+
+// GetTxStatus returns the status of [txID]
+// func (c *Client) GetTxStatus(txID ids.ID) (choices.Status, error) {
+// res := &GetTxStatusReply{}
+// err := c.requester.SendRequest("getTxStatus", &api.JSONTxID{
+// TxID: txID,
+// }, res)
+// return res.Status, err
+// }
+
+// GetTx returns the byte representation of [txID]
+func (c *Client) GetTx(txID ids.ID) ([]byte, error) {
+ res := &api.FormattedTx{}
+ err := c.requester.SendRequest("getTx", &api.GetTxArgs{
+ TxID: txID,
+ Encoding: formatting.Hex,
+ }, res)
+ if err != nil {
+ return nil, err
+ }
+
+ return formatting.Decode(formatting.Hex, res.Tx)
+}
+
+// GetUTXOs returns the byte representation of the UTXOs controlled by [addrs]
+func (c *Client) GetUTXOs(addrs []string, limit uint32, startAddress, startUTXOID string) ([][]byte, api.Index, error) {
+ res := &api.GetUTXOsReply{}
+ err := c.requester.SendRequest("getUTXOs", &api.GetUTXOsArgs{
+ Addresses: addrs,
+ Limit: cjson.Uint32(limit),
+ StartIndex: api.Index{
+ Address: startAddress,
+ UTXO: startUTXOID,
+ },
+ Encoding: formatting.Hex,
+ }, res)
+ if err != nil {
+ return nil, api.Index{}, err
+ }
+
+ utxos := make([][]byte, len(res.UTXOs))
+ for i, utxo := range res.UTXOs {
+ b, err := formatting.Decode(formatting.Hex, utxo)
+ if err != nil {
+ return nil, api.Index{}, err
+ }
+ utxos[i] = b
+ }
+ return utxos, res.EndIndex, nil
+}
+
+// CreateAddress creates a new address controlled by [user]
+func (c *Client) CreateAddress(user api.UserPass) (string, error) {
+ res := &api.JSONAddress{}
+ err := c.requester.SendRequest("createAddress", &user, res)
+ return res.Address, err
+}
+
+// ListAddresses returns all addresses on this chain controlled by [user]
+func (c *Client) ListAddresses(user api.UserPass) ([]string, error) {
+ res := &api.JSONAddresses{}
+ err := c.requester.SendRequest("listAddresses", &user, res)
+ return res.Addresses, err
+}
+
+// ExportKey returns the private key corresponding to [addr] controlled by [user]
+// in both Avalanche standard format and hex format
+func (c *Client) ExportKey(user api.UserPass, addr string) (string, string, error) {
+ res := &ExportKeyReply{}
+ err := c.requester.SendRequest("exportKey", &ExportKeyArgs{
+ UserPass: user,
+ Address: addr,
+ }, res)
+ return res.PrivateKey, res.PrivateKeyHex, err
+}
+
+// ImportKey imports [privateKey] to [user]
+func (c *Client) ImportKey(user api.UserPass, privateKey string) (string, error) {
+ res := &api.JSONAddress{}
+ err := c.requester.SendRequest("importKey", &ImportKeyArgs{
+ UserPass: user,
+ PrivateKey: privateKey,
+ }, res)
+ return res.Address, err
+}
+
+// Import sends an import transaction to import funds from [sourceChain] and
+// returns the ID of the newly created transaction
+func (c *Client) Import(user api.UserPass, to, sourceChain string) (ids.ID, error) {
+ res := &api.JSONTxID{}
+ err := c.requester.SendRequest("import", &ImportArgs{
+ UserPass: user,
+ To: to,
+ SourceChain: sourceChain,
+ }, res)
+ return res.TxID, err
+}
+
+// ExportAVAX sends AVAX from this chain to the address specified by [to].
+// Returns the ID of the newly created atomic transaction
+func (c *Client) ExportAVAX(
+ user api.UserPass,
+ amount uint64,
+ to string,
+) (ids.ID, error) {
+ return c.Export(user, amount, to, "AVAX")
+}
+
+// Export sends an asset from this chain to the P/C-Chain.
+// After this tx is accepted, the AVAX must be imported to the P/C-chain with an importTx.
+// Returns the ID of the newly created atomic transaction
+func (c *Client) Export(
+ user api.UserPass,
+ amount uint64,
+ to string,
+ assetID string,
+) (ids.ID, error) {
+ res := &api.JSONTxID{}
+ err := c.requester.SendRequest("export", &ExportArgs{
+ ExportAVAXArgs: ExportAVAXArgs{
+ UserPass: user,
+ Amount: cjson.Uint64(amount),
+ To: to,
+ },
+ AssetID: assetID,
+ }, res)
+ return res.TxID, err
+}