github.com/algorand/go-algorand-sdk@v1.24.0/test/transactions_test.go (about)

     1  package test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/algorand/go-algorand-sdk/crypto"
    11  	"github.com/algorand/go-algorand-sdk/future"
    12  	"github.com/algorand/go-algorand-sdk/mnemonic"
    13  	"github.com/algorand/go-algorand-sdk/types"
    14  	"github.com/cucumber/godog"
    15  
    16  	"golang.org/x/crypto/ed25519"
    17  )
    18  
    19  var sk1 ed25519.PrivateKey
    20  var addr1 types.Address
    21  
    22  func aSigningAccountWithAddressAndMnemonic(address, mnem string) error {
    23  	var err error
    24  	addr1, err = types.DecodeAddress(address)
    25  	if err != nil {
    26  		return err
    27  	}
    28  
    29  	sk1, err = mnemonic.ToPrivateKey(mnem)
    30  	account = crypto.Account{
    31  		Address:    addr1,
    32  		PrivateKey: sk1,
    33  		PublicKey:  ed25519.PublicKey(addr1[:]),
    34  	}
    35  
    36  	return err
    37  }
    38  
    39  func signTheTransaction() error {
    40  	var err error
    41  	txid, stx, err = crypto.SignTransaction(sk1, tx)
    42  	return err
    43  }
    44  
    45  func theBase64EncodedSignedTransactionShouldEqual(golden string) error {
    46  	gold, err := base64.StdEncoding.DecodeString(golden)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	if !bytes.Equal(gold, stx) {
    51  		toPrint := base64.StdEncoding.EncodeToString(stx)
    52  		return fmt.Errorf("Actual signed transaction does not match the expected. Got %s", toPrint)
    53  	}
    54  	return nil
    55  }
    56  
    57  func buildKeyregTransaction(sender, nonparticipation string,
    58  	voteFirst, voteLast, keyDilution int,
    59  	votePkB64, selectionPkB64, stateProofPkB64 string) error {
    60  
    61  	if voteFirst < 0 || voteLast < 0 || keyDilution < 0 {
    62  		return fmt.Errorf("Integer arguments cannot be negative")
    63  	}
    64  
    65  	nonPartValue, err := strconv.ParseBool(nonparticipation)
    66  	if err != nil {
    67  		return fmt.Errorf("Could not parse nonparticipation value: %v", err)
    68  	}
    69  
    70  	tx, err = future.MakeKeyRegTxnWithStateProofKey(sender, nil, sugParams, votePkB64, selectionPkB64, stateProofPkB64, uint64(voteFirst), uint64(voteLast), uint64(keyDilution), nonPartValue)
    71  	return err
    72  }
    73  
    74  // this function is a legacy step, we should get rid of it in favor one a newer step that works like
    75  // buildKeyregTransaction above
    76  func buildLegacyAppCallTransaction(
    77  	operation string,
    78  	applicationId int,
    79  	sender, approvalProgram, clearProgram string,
    80  	globalBytes, globalInts, localBytes, localInts int,
    81  	appArgs, foreignApps, foreignAssets, appAccounts string,
    82  	fee, firstValid, lastValid int,
    83  	genesisHash string, extraPages int, boxes string) error {
    84  
    85  	if applicationId < 0 || globalBytes < 0 || globalInts < 0 || localBytes < 0 || localInts < 0 || extraPages < 0 || fee < 0 || firstValid < 0 || lastValid < 0 {
    86  		return fmt.Errorf("Integer arguments cannot be negative")
    87  	}
    88  
    89  	senderAddr, err := types.DecodeAddress(sender)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	var approvalP []byte
    95  	if approvalProgram != "" {
    96  		approvalP, err = readTealProgram(approvalProgram)
    97  		if err != nil {
    98  			return err
    99  		}
   100  	}
   101  
   102  	var clearP []byte
   103  	if clearProgram != "" {
   104  		clearP, err = readTealProgram(clearProgram)
   105  		if err != nil {
   106  			return err
   107  		}
   108  	}
   109  
   110  	args, err := parseAppArgs(appArgs)
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	var accs []string
   116  	if appAccounts != "" {
   117  		accs = strings.Split(appAccounts, ",")
   118  	}
   119  
   120  	fApp, err := splitUint64(foreignApps)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	fAssets, err := splitUint64(foreignAssets)
   126  	if err != nil {
   127  		return err
   128  	}
   129  
   130  	boxReferences, err := parseBoxes(boxes)
   131  	if err != nil {
   132  		return err
   133  	}
   134  
   135  	gSchema := types.StateSchema{NumUint: uint64(globalInts), NumByteSlice: uint64(globalBytes)}
   136  	lSchema := types.StateSchema{NumUint: uint64(localInts), NumByteSlice: uint64(localBytes)}
   137  
   138  	gh, err := base64.StdEncoding.DecodeString(genesisHash)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	// this is only kept to keep compatibility with old features
   144  	// going forward, use txnSuggestedParams
   145  	sugParams = types.SuggestedParams{
   146  		Fee:             types.MicroAlgos(uint64(fee)),
   147  		GenesisID:       "",
   148  		GenesisHash:     gh,
   149  		FirstRoundValid: types.Round(firstValid),
   150  		LastRoundValid:  types.Round(lastValid),
   151  		FlatFee:         true,
   152  	}
   153  
   154  	switch operation {
   155  	case "create":
   156  		tx, err = future.MakeApplicationCreateTxWithBoxes(false, approvalP, clearP,
   157  			gSchema, lSchema, uint32(extraPages), args, accs, fApp, fAssets, boxReferences,
   158  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   159  	case "update":
   160  		tx, err = future.MakeApplicationUpdateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences,
   161  			approvalP, clearP,
   162  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   163  	case "call":
   164  		tx, err = future.MakeApplicationNoOpTxWithBoxes(uint64(applicationId), args, accs,
   165  			fApp, fAssets, boxReferences,
   166  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   167  	case "optin":
   168  		tx, err = future.MakeApplicationOptInTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences,
   169  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   170  	case "clear":
   171  		tx, err = future.MakeApplicationClearStateTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences,
   172  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   173  	case "closeout":
   174  		tx, err = future.MakeApplicationCloseOutTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences,
   175  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   176  	case "delete":
   177  		tx, err = future.MakeApplicationDeleteTxWithBoxes(uint64(applicationId), args, accs, fApp, fAssets, boxReferences,
   178  			sugParams, senderAddr, nil, types.Digest{}, [32]byte{}, types.Address{})
   179  	default:
   180  		err = fmt.Errorf("Unknown opperation: %s", operation)
   181  	}
   182  	return err
   183  
   184  }
   185  
   186  func TransactionsUnitContext(s *godog.Suite) {
   187  	// @unit.transactions
   188  	s.Step(`^a signing account with address "([^"]*)" and mnemonic "([^"]*)"$`, aSigningAccountWithAddressAndMnemonic)
   189  	s.Step(`^sign the transaction$`, signTheTransaction)
   190  	s.Step(`^the base64 encoded signed transaction should equal "([^"]*)"$`, theBase64EncodedSignedTransactionShouldEqual)
   191  	s.Step(`^the decoded transaction should equal the original$`, theDecodedTransactionShouldEqualTheOriginal)
   192  
   193  	// @unit.transactions.keyreg
   194  	s.Step(`^I build a keyreg transaction with sender "([^"]*)", nonparticipation "([^"]*)", vote first (\d+), vote last (\d+), key dilution (\d+), vote public key "([^"]*)", selection public key "([^"]*)", and state proof public key "([^"]*)"$`, buildKeyregTransaction)
   195  	s.Step(`^I build an application transaction with operation "([^"]*)", application-id (\d+), sender "([^"]*)", approval-program "([^"]*)", clear-program "([^"]*)", global-bytes (\d+), global-ints (\d+), local-bytes (\d+), local-ints (\d+), app-args "([^"]*)", foreign-apps "([^"]*)", foreign-assets "([^"]*)", app-accounts "([^"]*)", fee (\d+), first-valid (\d+), last-valid (\d+), genesis-hash "([^"]*)", extra-pages (\d+), boxes "([^"]*)"$`, buildLegacyAppCallTransaction)
   196  }