github.com/MetalBlockchain/metalgo@v1.11.9/vms/avm/wallet_client.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package avm
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/MetalBlockchain/metalgo/api"
    11  	"github.com/MetalBlockchain/metalgo/ids"
    12  	"github.com/MetalBlockchain/metalgo/utils/constants"
    13  	"github.com/MetalBlockchain/metalgo/utils/formatting"
    14  	"github.com/MetalBlockchain/metalgo/utils/json"
    15  	"github.com/MetalBlockchain/metalgo/utils/rpc"
    16  )
    17  
    18  var _ WalletClient = (*client)(nil)
    19  
    20  // interface of an AVM wallet client for interacting with avm managed wallet on [chain]
    21  type WalletClient interface {
    22  	// IssueTx issues a transaction to a node and returns the TxID
    23  	IssueTx(ctx context.Context, tx []byte, options ...rpc.Option) (ids.ID, error)
    24  	// Send [amount] of [assetID] to address [to]
    25  	//
    26  	// Deprecated: Transactions should be issued using the
    27  	// `avalanchego/wallet/chain/x.Wallet` utility.
    28  	Send(
    29  		ctx context.Context,
    30  		user api.UserPass,
    31  		from []ids.ShortID,
    32  		changeAddr ids.ShortID,
    33  		amount uint64,
    34  		assetID string,
    35  		to ids.ShortID,
    36  		memo string,
    37  		options ...rpc.Option,
    38  	) (ids.ID, error)
    39  	// SendMultiple sends a transaction from [user] funding all [outputs]
    40  	//
    41  	// Deprecated: Transactions should be issued using the
    42  	// `avalanchego/wallet/chain/x.Wallet` utility.
    43  	SendMultiple(
    44  		ctx context.Context,
    45  		user api.UserPass,
    46  		from []ids.ShortID,
    47  		changeAddr ids.ShortID,
    48  		outputs []ClientSendOutput,
    49  		memo string,
    50  		options ...rpc.Option,
    51  	) (ids.ID, error)
    52  }
    53  
    54  // implementation of an AVM wallet client for interacting with avm managed wallet on [chain]
    55  type walletClient struct {
    56  	requester rpc.EndpointRequester
    57  }
    58  
    59  // NewWalletClient returns an AVM wallet client for interacting with avm managed wallet on [chain]
    60  //
    61  // Deprecated: Transactions should be issued using the
    62  // `avalanchego/wallet/chain/x.Wallet` utility.
    63  func NewWalletClient(uri, chain string) WalletClient {
    64  	path := fmt.Sprintf(
    65  		"%s/ext/%s/%s/wallet",
    66  		uri,
    67  		constants.ChainAliasPrefix,
    68  		chain,
    69  	)
    70  	return &walletClient{
    71  		requester: rpc.NewEndpointRequester(path),
    72  	}
    73  }
    74  
    75  func (c *walletClient) IssueTx(ctx context.Context, txBytes []byte, options ...rpc.Option) (ids.ID, error) {
    76  	txStr, err := formatting.Encode(formatting.Hex, txBytes)
    77  	if err != nil {
    78  		return ids.Empty, err
    79  	}
    80  	res := &api.JSONTxID{}
    81  	err = c.requester.SendRequest(ctx, "wallet.issueTx", &api.FormattedTx{
    82  		Tx:       txStr,
    83  		Encoding: formatting.Hex,
    84  	}, res, options...)
    85  	return res.TxID, err
    86  }
    87  
    88  // ClientSendOutput specifies that [Amount] of asset [AssetID] be sent to [To]
    89  type ClientSendOutput struct {
    90  	// The amount of funds to send
    91  	Amount uint64
    92  
    93  	// ID of the asset being sent
    94  	AssetID string
    95  
    96  	// Address of the recipient
    97  	To ids.ShortID
    98  }
    99  
   100  func (c *walletClient) Send(
   101  	ctx context.Context,
   102  	user api.UserPass,
   103  	from []ids.ShortID,
   104  	changeAddr ids.ShortID,
   105  	amount uint64,
   106  	assetID string,
   107  	to ids.ShortID,
   108  	memo string,
   109  	options ...rpc.Option,
   110  ) (ids.ID, error) {
   111  	res := &api.JSONTxID{}
   112  	err := c.requester.SendRequest(ctx, "wallet.send", &SendArgs{
   113  		JSONSpendHeader: api.JSONSpendHeader{
   114  			UserPass:       user,
   115  			JSONFromAddrs:  api.JSONFromAddrs{From: ids.ShortIDsToStrings(from)},
   116  			JSONChangeAddr: api.JSONChangeAddr{ChangeAddr: changeAddr.String()},
   117  		},
   118  		SendOutput: SendOutput{
   119  			Amount:  json.Uint64(amount),
   120  			AssetID: assetID,
   121  			To:      to.String(),
   122  		},
   123  		Memo: memo,
   124  	}, res, options...)
   125  	return res.TxID, err
   126  }
   127  
   128  func (c *walletClient) SendMultiple(
   129  	ctx context.Context,
   130  	user api.UserPass,
   131  	from []ids.ShortID,
   132  	changeAddr ids.ShortID,
   133  	outputs []ClientSendOutput,
   134  	memo string,
   135  	options ...rpc.Option,
   136  ) (ids.ID, error) {
   137  	res := &api.JSONTxID{}
   138  	serviceOutputs := make([]SendOutput, len(outputs))
   139  	for i, output := range outputs {
   140  		serviceOutputs[i].Amount = json.Uint64(output.Amount)
   141  		serviceOutputs[i].AssetID = output.AssetID
   142  		serviceOutputs[i].To = output.To.String()
   143  	}
   144  	err := c.requester.SendRequest(ctx, "wallet.sendMultiple", &SendMultipleArgs{
   145  		JSONSpendHeader: api.JSONSpendHeader{
   146  			UserPass:       user,
   147  			JSONFromAddrs:  api.JSONFromAddrs{From: ids.ShortIDsToStrings(from)},
   148  			JSONChangeAddr: api.JSONChangeAddr{ChangeAddr: changeAddr.String()},
   149  		},
   150  		Outputs: serviceOutputs,
   151  		Memo:    memo,
   152  	}, res, options...)
   153  	return res.TxID, err
   154  }