github.com/ava-labs/avalanchego@v1.11.11/vms/avm/txs/txstest/builder.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package txstest
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/ava-labs/avalanchego/codec"
    11  	"github.com/ava-labs/avalanchego/ids"
    12  	"github.com/ava-labs/avalanchego/snow"
    13  	"github.com/ava-labs/avalanchego/vms/avm/config"
    14  	"github.com/ava-labs/avalanchego/vms/avm/state"
    15  	"github.com/ava-labs/avalanchego/vms/avm/txs"
    16  	"github.com/ava-labs/avalanchego/vms/components/avax"
    17  	"github.com/ava-labs/avalanchego/vms/components/verify"
    18  	"github.com/ava-labs/avalanchego/vms/secp256k1fx"
    19  	"github.com/ava-labs/avalanchego/wallet/chain/x/builder"
    20  	"github.com/ava-labs/avalanchego/wallet/chain/x/signer"
    21  	"github.com/ava-labs/avalanchego/wallet/subnet/primary/common"
    22  )
    23  
    24  type Builder struct {
    25  	utxos *utxos
    26  	ctx   *builder.Context
    27  }
    28  
    29  func New(
    30  	codec codec.Manager,
    31  	ctx *snow.Context,
    32  	cfg *config.Config,
    33  	feeAssetID ids.ID,
    34  	state state.State,
    35  ) *Builder {
    36  	utxos := newUTXOs(ctx, state, ctx.SharedMemory, codec)
    37  	return &Builder{
    38  		utxos: utxos,
    39  		ctx:   newContext(ctx, cfg, feeAssetID),
    40  	}
    41  }
    42  
    43  func (b *Builder) CreateAssetTx(
    44  	name, symbol string,
    45  	denomination byte,
    46  	initialStates map[uint32][]verify.State,
    47  	kc *secp256k1fx.Keychain,
    48  	changeAddr ids.ShortID,
    49  ) (*txs.Tx, error) {
    50  	xBuilder, xSigner := b.builders(kc)
    51  
    52  	utx, err := xBuilder.NewCreateAssetTx(
    53  		name,
    54  		symbol,
    55  		denomination,
    56  		initialStates,
    57  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
    58  			Threshold: 1,
    59  			Addrs:     []ids.ShortID{changeAddr},
    60  		}),
    61  	)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("failed building base tx: %w", err)
    64  	}
    65  
    66  	return signer.SignUnsigned(context.Background(), xSigner, utx)
    67  }
    68  
    69  func (b *Builder) BaseTx(
    70  	outs []*avax.TransferableOutput,
    71  	memo []byte,
    72  	kc *secp256k1fx.Keychain,
    73  	changeAddr ids.ShortID,
    74  ) (*txs.Tx, error) {
    75  	xBuilder, xSigner := b.builders(kc)
    76  
    77  	utx, err := xBuilder.NewBaseTx(
    78  		outs,
    79  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
    80  			Threshold: 1,
    81  			Addrs:     []ids.ShortID{changeAddr},
    82  		}),
    83  		common.WithMemo(memo),
    84  	)
    85  	if err != nil {
    86  		return nil, fmt.Errorf("failed building base tx: %w", err)
    87  	}
    88  
    89  	return signer.SignUnsigned(context.Background(), xSigner, utx)
    90  }
    91  
    92  func (b *Builder) MintNFT(
    93  	assetID ids.ID,
    94  	payload []byte,
    95  	owners []*secp256k1fx.OutputOwners,
    96  	kc *secp256k1fx.Keychain,
    97  	changeAddr ids.ShortID,
    98  ) (*txs.Tx, error) {
    99  	xBuilder, xSigner := b.builders(kc)
   100  
   101  	utx, err := xBuilder.NewOperationTxMintNFT(
   102  		assetID,
   103  		payload,
   104  		owners,
   105  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
   106  			Threshold: 1,
   107  			Addrs:     []ids.ShortID{changeAddr},
   108  		}),
   109  	)
   110  	if err != nil {
   111  		return nil, fmt.Errorf("failed minting NFTs: %w", err)
   112  	}
   113  
   114  	return signer.SignUnsigned(context.Background(), xSigner, utx)
   115  }
   116  
   117  func (b *Builder) MintFTs(
   118  	outputs map[ids.ID]*secp256k1fx.TransferOutput,
   119  	kc *secp256k1fx.Keychain,
   120  	changeAddr ids.ShortID,
   121  ) (*txs.Tx, error) {
   122  	xBuilder, xSigner := b.builders(kc)
   123  
   124  	utx, err := xBuilder.NewOperationTxMintFT(
   125  		outputs,
   126  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
   127  			Threshold: 1,
   128  			Addrs:     []ids.ShortID{changeAddr},
   129  		}),
   130  	)
   131  	if err != nil {
   132  		return nil, fmt.Errorf("failed minting FTs: %w", err)
   133  	}
   134  
   135  	return signer.SignUnsigned(context.Background(), xSigner, utx)
   136  }
   137  
   138  func (b *Builder) Operation(
   139  	ops []*txs.Operation,
   140  	kc *secp256k1fx.Keychain,
   141  	changeAddr ids.ShortID,
   142  ) (*txs.Tx, error) {
   143  	xBuilder, xSigner := b.builders(kc)
   144  
   145  	utx, err := xBuilder.NewOperationTx(
   146  		ops,
   147  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
   148  			Threshold: 1,
   149  			Addrs:     []ids.ShortID{changeAddr},
   150  		}),
   151  	)
   152  	if err != nil {
   153  		return nil, fmt.Errorf("failed building operation tx: %w", err)
   154  	}
   155  
   156  	return signer.SignUnsigned(context.Background(), xSigner, utx)
   157  }
   158  
   159  func (b *Builder) ImportTx(
   160  	sourceChain ids.ID,
   161  	to ids.ShortID,
   162  	kc *secp256k1fx.Keychain,
   163  ) (*txs.Tx, error) {
   164  	xBuilder, xSigner := b.builders(kc)
   165  
   166  	outOwner := &secp256k1fx.OutputOwners{
   167  		Locktime:  0,
   168  		Threshold: 1,
   169  		Addrs:     []ids.ShortID{to},
   170  	}
   171  
   172  	utx, err := xBuilder.NewImportTx(
   173  		sourceChain,
   174  		outOwner,
   175  	)
   176  	if err != nil {
   177  		return nil, fmt.Errorf("failed building import tx: %w", err)
   178  	}
   179  
   180  	return signer.SignUnsigned(context.Background(), xSigner, utx)
   181  }
   182  
   183  func (b *Builder) ExportTx(
   184  	destinationChain ids.ID,
   185  	to ids.ShortID,
   186  	exportedAssetID ids.ID,
   187  	exportedAmt uint64,
   188  	kc *secp256k1fx.Keychain,
   189  	changeAddr ids.ShortID,
   190  ) (*txs.Tx, error) {
   191  	xBuilder, xSigner := b.builders(kc)
   192  
   193  	outputs := []*avax.TransferableOutput{{
   194  		Asset: avax.Asset{ID: exportedAssetID},
   195  		Out: &secp256k1fx.TransferOutput{
   196  			Amt: exportedAmt,
   197  			OutputOwners: secp256k1fx.OutputOwners{
   198  				Locktime:  0,
   199  				Threshold: 1,
   200  				Addrs:     []ids.ShortID{to},
   201  			},
   202  		},
   203  	}}
   204  
   205  	utx, err := xBuilder.NewExportTx(
   206  		destinationChain,
   207  		outputs,
   208  		common.WithChangeOwner(&secp256k1fx.OutputOwners{
   209  			Threshold: 1,
   210  			Addrs:     []ids.ShortID{changeAddr},
   211  		}),
   212  	)
   213  	if err != nil {
   214  		return nil, fmt.Errorf("failed building export tx: %w", err)
   215  	}
   216  
   217  	return signer.SignUnsigned(context.Background(), xSigner, utx)
   218  }
   219  
   220  func (b *Builder) builders(kc *secp256k1fx.Keychain) (builder.Builder, signer.Signer) {
   221  	var (
   222  		addrs = kc.Addresses()
   223  		wa    = &walletUTXOsAdapter{
   224  			utxos: b.utxos,
   225  			addrs: addrs,
   226  		}
   227  		builder = builder.New(addrs, b.ctx, wa)
   228  		signer  = signer.New(kc, wa)
   229  	)
   230  	return builder, signer
   231  }