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 }