github.com/ava-labs/avalanchego@v1.11.11/wallet/subnet/primary/wallet.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package primary
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/ava-labs/avalanchego/ids"
    10  	"github.com/ava-labs/avalanchego/utils/constants"
    11  	"github.com/ava-labs/avalanchego/utils/crypto/keychain"
    12  	"github.com/ava-labs/avalanchego/vms/platformvm"
    13  	"github.com/ava-labs/avalanchego/wallet/chain/c"
    14  	"github.com/ava-labs/avalanchego/wallet/chain/p"
    15  	"github.com/ava-labs/avalanchego/wallet/chain/x"
    16  	"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
    17  
    18  	pbuilder "github.com/ava-labs/avalanchego/wallet/chain/p/builder"
    19  	psigner "github.com/ava-labs/avalanchego/wallet/chain/p/signer"
    20  	pwallet "github.com/ava-labs/avalanchego/wallet/chain/p/wallet"
    21  	xbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder"
    22  	xsigner "github.com/ava-labs/avalanchego/wallet/chain/x/signer"
    23  )
    24  
    25  var _ Wallet = (*wallet)(nil)
    26  
    27  // Wallet provides chain wallets for the primary network.
    28  type Wallet interface {
    29  	P() pwallet.Wallet
    30  	X() x.Wallet
    31  	C() c.Wallet
    32  }
    33  
    34  type wallet struct {
    35  	p pwallet.Wallet
    36  	x x.Wallet
    37  	c c.Wallet
    38  }
    39  
    40  func (w *wallet) P() pwallet.Wallet {
    41  	return w.p
    42  }
    43  
    44  func (w *wallet) X() x.Wallet {
    45  	return w.x
    46  }
    47  
    48  func (w *wallet) C() c.Wallet {
    49  	return w.c
    50  }
    51  
    52  // Creates a new default wallet
    53  func NewWallet(p pwallet.Wallet, x x.Wallet, c c.Wallet) Wallet {
    54  	return &wallet{
    55  		p: p,
    56  		x: x,
    57  		c: c,
    58  	}
    59  }
    60  
    61  // Creates a Wallet with the given set of options
    62  func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet {
    63  	return NewWallet(
    64  		pwallet.WithOptions(w.P(), options...),
    65  		x.NewWalletWithOptions(w.X(), options...),
    66  		c.NewWalletWithOptions(w.C(), options...),
    67  	)
    68  }
    69  
    70  type WalletConfig struct {
    71  	// Base URI to use for all node requests.
    72  	URI string // required
    73  	// Keys to use for signing all transactions.
    74  	AVAXKeychain keychain.Keychain // required
    75  	EthKeychain  c.EthKeychain     // required
    76  	// Subnet IDs that the wallet should know about to be able to
    77  	// generate transactions.
    78  	SubnetIDs []ids.ID // optional
    79  }
    80  
    81  // MakeWallet returns a wallet that supports issuing transactions to the chains
    82  // living in the primary network.
    83  //
    84  // On creation, the wallet attaches to the provided uri and fetches all UTXOs
    85  // that reference any of the provided keys. If the UTXOs are modified through an
    86  // external issuance process, such as another instance of the wallet, the UTXOs
    87  // may become out of sync. The wallet will also fetch all requested P-chain
    88  // transactions.
    89  //
    90  // The wallet manages all state locally, and performs all tx signing locally.
    91  func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) {
    92  	avaxAddrs := config.AVAXKeychain.Addresses()
    93  	avaxState, err := FetchState(ctx, config.URI, avaxAddrs)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	ethAddrs := config.EthKeychain.EthAddresses()
    99  	ethState, err := FetchEthState(ctx, config.URI, ethAddrs)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	subnetOwners, err := platformvm.GetSubnetOwners(avaxState.PClient, ctx, config.SubnetIDs...)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	pUTXOs := common.NewChainUTXOs(constants.PlatformChainID, avaxState.UTXOs)
   109  	pBackend := pwallet.NewBackend(avaxState.PCTX, pUTXOs, subnetOwners)
   110  	pClient := p.NewClient(avaxState.PClient, pBackend)
   111  	pBuilder := pbuilder.New(avaxAddrs, avaxState.PCTX, pBackend)
   112  	pSigner := psigner.New(config.AVAXKeychain, pBackend)
   113  
   114  	xChainID := avaxState.XCTX.BlockchainID
   115  	xUTXOs := common.NewChainUTXOs(xChainID, avaxState.UTXOs)
   116  	xBackend := x.NewBackend(avaxState.XCTX, xUTXOs)
   117  	xBuilder := xbuilder.New(avaxAddrs, avaxState.XCTX, xBackend)
   118  	xSigner := xsigner.New(config.AVAXKeychain, xBackend)
   119  
   120  	cChainID := avaxState.CCTX.BlockchainID
   121  	cUTXOs := common.NewChainUTXOs(cChainID, avaxState.UTXOs)
   122  	cBackend := c.NewBackend(cUTXOs, ethState.Accounts)
   123  	cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, avaxState.CCTX, cBackend)
   124  	cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend)
   125  
   126  	return NewWallet(
   127  		pwallet.New(pClient, pBuilder, pSigner),
   128  		x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend),
   129  		c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend),
   130  	), nil
   131  }