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 }