github.com/ava-labs/avalanchego@v1.11.11/wallet/chain/x/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 x
     5  
     6  import (
     7  	"github.com/ava-labs/avalanchego/ids"
     8  	"github.com/ava-labs/avalanchego/vms/avm"
     9  	"github.com/ava-labs/avalanchego/vms/avm/txs"
    10  	"github.com/ava-labs/avalanchego/vms/components/avax"
    11  	"github.com/ava-labs/avalanchego/vms/components/verify"
    12  	"github.com/ava-labs/avalanchego/vms/secp256k1fx"
    13  	"github.com/ava-labs/avalanchego/wallet/chain/x/builder"
    14  	"github.com/ava-labs/avalanchego/wallet/chain/x/signer"
    15  	"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
    16  )
    17  
    18  var _ Wallet = (*wallet)(nil)
    19  
    20  type Wallet interface {
    21  	// Builder returns the builder that will be used to create the transactions.
    22  	Builder() builder.Builder
    23  
    24  	// Signer returns the signer that will be used to sign the transactions.
    25  	Signer() signer.Signer
    26  
    27  	// IssueBaseTx creates, signs, and issues a new simple value transfer.
    28  	//
    29  	// - [outputs] specifies all the recipients and amounts that should be sent
    30  	//   from this transaction.
    31  	IssueBaseTx(
    32  		outputs []*avax.TransferableOutput,
    33  		options ...common.Option,
    34  	) (*txs.Tx, error)
    35  
    36  	// IssueCreateAssetTx creates, signs, and issues a new asset.
    37  	//
    38  	// - [name] specifies a human readable name for this asset.
    39  	// - [symbol] specifies a human readable abbreviation for this asset.
    40  	// - [denomination] specifies how many times the asset can be split. For
    41  	//   example, a denomination of [4] would mean that the smallest unit of the
    42  	//   asset would be 0.001 units.
    43  	// - [initialState] specifies the supported feature extensions for this
    44  	//   asset as well as the initial outputs for the asset.
    45  	IssueCreateAssetTx(
    46  		name string,
    47  		symbol string,
    48  		denomination byte,
    49  		initialState map[uint32][]verify.State,
    50  		options ...common.Option,
    51  	) (*txs.Tx, error)
    52  
    53  	// IssueOperationTx creates, signs, and issues state changes on the UTXO
    54  	// set. These state changes may be more complex than simple value transfers.
    55  	//
    56  	// - [operations] specifies the state changes to perform.
    57  	IssueOperationTx(
    58  		operations []*txs.Operation,
    59  		options ...common.Option,
    60  	) (*txs.Tx, error)
    61  
    62  	// IssueOperationTxMintFT creates, signs, and issues a set of state changes
    63  	// that mint new tokens for the requested assets.
    64  	//
    65  	// - [outputs] maps the assetID to the output that should be created for the
    66  	//   asset.
    67  	IssueOperationTxMintFT(
    68  		outputs map[ids.ID]*secp256k1fx.TransferOutput,
    69  		options ...common.Option,
    70  	) (*txs.Tx, error)
    71  
    72  	// IssueOperationTxMintNFT creates, signs, and issues a state change that
    73  	// mints new NFTs for the requested asset.
    74  	//
    75  	// - [assetID] specifies the asset to mint the NFTs under.
    76  	// - [payload] specifies the payload to provide each new NFT.
    77  	// - [owners] specifies the new owners of each NFT.
    78  	IssueOperationTxMintNFT(
    79  		assetID ids.ID,
    80  		payload []byte,
    81  		owners []*secp256k1fx.OutputOwners,
    82  		options ...common.Option,
    83  	) (*txs.Tx, error)
    84  
    85  	// IssueOperationTxMintProperty creates, signs, and issues a state change
    86  	// that mints a new property for the requested asset.
    87  	//
    88  	// - [assetID] specifies the asset to mint the property under.
    89  	// - [owner] specifies the new owner of the property.
    90  	IssueOperationTxMintProperty(
    91  		assetID ids.ID,
    92  		owner *secp256k1fx.OutputOwners,
    93  		options ...common.Option,
    94  	) (*txs.Tx, error)
    95  
    96  	// IssueOperationTxBurnProperty creates, signs, and issues state changes
    97  	// that burns all the properties of the requested asset.
    98  	//
    99  	// - [assetID] specifies the asset to burn the property of.
   100  	IssueOperationTxBurnProperty(
   101  		assetID ids.ID,
   102  		options ...common.Option,
   103  	) (*txs.Tx, error)
   104  
   105  	// IssueImportTx creates, signs, and issues an import transaction that
   106  	// attempts to consume all the available UTXOs and import the funds to [to].
   107  	//
   108  	// - [chainID] specifies the chain to be importing funds from.
   109  	// - [to] specifies where to send the imported funds to.
   110  	IssueImportTx(
   111  		chainID ids.ID,
   112  		to *secp256k1fx.OutputOwners,
   113  		options ...common.Option,
   114  	) (*txs.Tx, error)
   115  
   116  	// IssueExportTx creates, signs, and issues an export transaction that
   117  	// attempts to send all the provided [outputs] to the requested [chainID].
   118  	//
   119  	// - [chainID] specifies the chain to be exporting the funds to.
   120  	// - [outputs] specifies the outputs to send to the [chainID].
   121  	IssueExportTx(
   122  		chainID ids.ID,
   123  		outputs []*avax.TransferableOutput,
   124  		options ...common.Option,
   125  	) (*txs.Tx, error)
   126  
   127  	// IssueUnsignedTx signs and issues the unsigned tx.
   128  	IssueUnsignedTx(
   129  		utx txs.UnsignedTx,
   130  		options ...common.Option,
   131  	) (*txs.Tx, error)
   132  
   133  	// IssueTx issues the signed tx.
   134  	IssueTx(
   135  		tx *txs.Tx,
   136  		options ...common.Option,
   137  	) error
   138  }
   139  
   140  func NewWallet(
   141  	builder builder.Builder,
   142  	signer signer.Signer,
   143  	client avm.Client,
   144  	backend Backend,
   145  ) Wallet {
   146  	return &wallet{
   147  		backend: backend,
   148  		builder: builder,
   149  		signer:  signer,
   150  		client:  client,
   151  	}
   152  }
   153  
   154  type wallet struct {
   155  	backend Backend
   156  	builder builder.Builder
   157  	signer  signer.Signer
   158  	client  avm.Client
   159  }
   160  
   161  func (w *wallet) Builder() builder.Builder {
   162  	return w.builder
   163  }
   164  
   165  func (w *wallet) Signer() signer.Signer {
   166  	return w.signer
   167  }
   168  
   169  func (w *wallet) IssueBaseTx(
   170  	outputs []*avax.TransferableOutput,
   171  	options ...common.Option,
   172  ) (*txs.Tx, error) {
   173  	utx, err := w.builder.NewBaseTx(outputs, options...)
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	return w.IssueUnsignedTx(utx, options...)
   178  }
   179  
   180  func (w *wallet) IssueCreateAssetTx(
   181  	name string,
   182  	symbol string,
   183  	denomination byte,
   184  	initialState map[uint32][]verify.State,
   185  	options ...common.Option,
   186  ) (*txs.Tx, error) {
   187  	utx, err := w.builder.NewCreateAssetTx(name, symbol, denomination, initialState, options...)
   188  	if err != nil {
   189  		return nil, err
   190  	}
   191  	return w.IssueUnsignedTx(utx, options...)
   192  }
   193  
   194  func (w *wallet) IssueOperationTx(
   195  	operations []*txs.Operation,
   196  	options ...common.Option,
   197  ) (*txs.Tx, error) {
   198  	utx, err := w.builder.NewOperationTx(operations, options...)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	return w.IssueUnsignedTx(utx, options...)
   203  }
   204  
   205  func (w *wallet) IssueOperationTxMintFT(
   206  	outputs map[ids.ID]*secp256k1fx.TransferOutput,
   207  	options ...common.Option,
   208  ) (*txs.Tx, error) {
   209  	utx, err := w.builder.NewOperationTxMintFT(outputs, options...)
   210  	if err != nil {
   211  		return nil, err
   212  	}
   213  	return w.IssueUnsignedTx(utx, options...)
   214  }
   215  
   216  func (w *wallet) IssueOperationTxMintNFT(
   217  	assetID ids.ID,
   218  	payload []byte,
   219  	owners []*secp256k1fx.OutputOwners,
   220  	options ...common.Option,
   221  ) (*txs.Tx, error) {
   222  	utx, err := w.builder.NewOperationTxMintNFT(assetID, payload, owners, options...)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	return w.IssueUnsignedTx(utx, options...)
   227  }
   228  
   229  func (w *wallet) IssueOperationTxMintProperty(
   230  	assetID ids.ID,
   231  	owner *secp256k1fx.OutputOwners,
   232  	options ...common.Option,
   233  ) (*txs.Tx, error) {
   234  	utx, err := w.builder.NewOperationTxMintProperty(assetID, owner, options...)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	return w.IssueUnsignedTx(utx, options...)
   239  }
   240  
   241  func (w *wallet) IssueOperationTxBurnProperty(
   242  	assetID ids.ID,
   243  	options ...common.Option,
   244  ) (*txs.Tx, error) {
   245  	utx, err := w.builder.NewOperationTxBurnProperty(assetID, options...)
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  	return w.IssueUnsignedTx(utx, options...)
   250  }
   251  
   252  func (w *wallet) IssueImportTx(
   253  	chainID ids.ID,
   254  	to *secp256k1fx.OutputOwners,
   255  	options ...common.Option,
   256  ) (*txs.Tx, error) {
   257  	utx, err := w.builder.NewImportTx(chainID, to, options...)
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  	return w.IssueUnsignedTx(utx, options...)
   262  }
   263  
   264  func (w *wallet) IssueExportTx(
   265  	chainID ids.ID,
   266  	outputs []*avax.TransferableOutput,
   267  	options ...common.Option,
   268  ) (*txs.Tx, error) {
   269  	utx, err := w.builder.NewExportTx(chainID, outputs, options...)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  	return w.IssueUnsignedTx(utx, options...)
   274  }
   275  
   276  func (w *wallet) IssueUnsignedTx(
   277  	utx txs.UnsignedTx,
   278  	options ...common.Option,
   279  ) (*txs.Tx, error) {
   280  	ops := common.NewOptions(options)
   281  	ctx := ops.Context()
   282  	tx, err := signer.SignUnsigned(ctx, w.signer, utx)
   283  	if err != nil {
   284  		return nil, err
   285  	}
   286  
   287  	return tx, w.IssueTx(tx, options...)
   288  }
   289  
   290  func (w *wallet) IssueTx(
   291  	tx *txs.Tx,
   292  	options ...common.Option,
   293  ) error {
   294  	ops := common.NewOptions(options)
   295  	ctx := ops.Context()
   296  	txID, err := w.client.IssueTx(ctx, tx.Bytes())
   297  	if err != nil {
   298  		return err
   299  	}
   300  
   301  	if f := ops.PostIssuanceFunc(); f != nil {
   302  		f(txID)
   303  	}
   304  
   305  	if ops.AssumeDecided() {
   306  		return w.backend.AcceptTx(ctx, tx)
   307  	}
   308  
   309  	if err := avm.AwaitTxAccepted(w.client, ctx, txID, ops.PollFrequency()); err != nil {
   310  		return err
   311  	}
   312  
   313  	return w.backend.AcceptTx(ctx, tx)
   314  }