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

     1  package test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/base32"
     7  	"encoding/base64"
     8  	"encoding/gob"
     9  	"encoding/hex"
    10  	"encoding/json"
    11  	"flag"
    12  	"fmt"
    13  	"os"
    14  	"path"
    15  	"reflect"
    16  	"strconv"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"golang.org/x/crypto/ed25519"
    22  
    23  	"github.com/algorand/go-algorand-sdk/abi"
    24  	"github.com/algorand/go-algorand-sdk/auction"
    25  	"github.com/algorand/go-algorand-sdk/client/kmd"
    26  	algodV2 "github.com/algorand/go-algorand-sdk/client/v2/algod"
    27  	commonV2 "github.com/algorand/go-algorand-sdk/client/v2/common"
    28  	modelsV2 "github.com/algorand/go-algorand-sdk/client/v2/common/models"
    29  	indexerV2 "github.com/algorand/go-algorand-sdk/client/v2/indexer"
    30  	"github.com/algorand/go-algorand-sdk/crypto"
    31  	"github.com/algorand/go-algorand-sdk/encoding/msgpack"
    32  	"github.com/algorand/go-algorand-sdk/future"
    33  	"github.com/algorand/go-algorand-sdk/logic"
    34  	"github.com/algorand/go-algorand-sdk/mnemonic"
    35  	"github.com/algorand/go-algorand-sdk/types"
    36  	"github.com/cucumber/godog"
    37  	"github.com/cucumber/godog/colors"
    38  )
    39  
    40  var txn types.Transaction
    41  var stx []byte
    42  var stxKmd []byte
    43  var stxObj types.SignedTxn
    44  var txid string
    45  var account crypto.Account
    46  var note []byte
    47  var fee uint64
    48  var fv uint64
    49  var lv uint64
    50  var to string
    51  var gh []byte
    52  var close string
    53  var amt uint64
    54  var gen string
    55  var a types.Address
    56  var msig crypto.MultisigAccount
    57  var msigsig types.MultisigSig
    58  var kcl kmd.Client
    59  var aclv2 *algodV2.Client
    60  var iclv2 *indexerV2.Client
    61  var walletName string
    62  var walletPswd string
    63  var walletID string
    64  var handle string
    65  var versions []string
    66  var msigExp kmd.ExportMultisigResponse
    67  var pk string
    68  var rekey string
    69  var accounts []string
    70  var e bool
    71  var lastRound uint64
    72  var sugParams types.SuggestedParams
    73  var bid types.Bid
    74  var sbid types.NoteField
    75  var oldBid types.NoteField
    76  var oldPk string
    77  var newMn string
    78  var mdk types.MasterDerivationKey
    79  var microalgos types.MicroAlgos
    80  var bytetxs [][]byte
    81  var votekey string
    82  var selkey string
    83  var stateProofPK string
    84  var votefst uint64
    85  var votelst uint64
    86  var votekd uint64
    87  var nonpart bool
    88  var data []byte
    89  var sig types.Signature
    90  var abiMethod abi.Method
    91  var abiMethods []abi.Method
    92  var abiJsonString string
    93  var abiInterface abi.Interface
    94  var abiContract abi.Contract
    95  var txComposer future.AtomicTransactionComposer
    96  var accountTxSigner future.BasicAccountTransactionSigner
    97  var methodArgs []interface{}
    98  var sigTxs [][]byte
    99  var accountTxAndSigner future.TransactionWithSigner
   100  var txTrace future.DryrunTxnResult
   101  var trace string
   102  var sourceMap logic.SourceMap
   103  var srcMapping map[string]interface{}
   104  var seeminglyProgram []byte
   105  var sanityCheckError error
   106  
   107  var assetTestFixture struct {
   108  	Creator               string
   109  	AssetIndex            uint64
   110  	AssetName             string
   111  	AssetUnitName         string
   112  	AssetURL              string
   113  	AssetMetadataHash     string
   114  	ExpectedParams        modelsV2.AssetParams
   115  	QueriedParams         modelsV2.AssetParams
   116  	LastTransactionIssued types.Transaction
   117  }
   118  
   119  var tealCompleResult struct {
   120  	status   int
   121  	response modelsV2.CompileResponse
   122  }
   123  
   124  var tealDryrunResult struct {
   125  	status   int
   126  	response modelsV2.DryrunResponse
   127  }
   128  
   129  var opt = godog.Options{
   130  	Output: colors.Colored(os.Stdout),
   131  	Format: "progress", // can define default values
   132  }
   133  
   134  // Dev mode helper functions
   135  const devModeInitialAmount = 10_000_000
   136  
   137  /**
   138   * waitForAlgodInDevMode is a Dev mode helper method
   139   * to wait for blocks to be finalized.
   140   * Since Dev mode produces blocks on a per transaction basis, it's possible
   141   * algod generates a block _before_ the corresponding SDK call to wait for a block.
   142   * Without _any_ wait, it's possible the SDK looks for the transaction before algod completes processing.
   143   * So, the method performs a local sleep to simulate waiting for a block.
   144   */
   145  func waitForAlgodInDevMode() {
   146  	time.Sleep(500 * time.Millisecond)
   147  }
   148  
   149  func initializeAccount(accountAddress string) error {
   150  	params, err := aclv2.SuggestedParams().Do(context.Background())
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	txn, err = future.MakePaymentTxn(accounts[0], accountAddress, devModeInitialAmount, []byte{}, "", params)
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	res, err := kcl.SignTransaction(handle, walletPswd, txn)
   161  	if err != nil {
   162  		return err
   163  	}
   164  
   165  	_, err = aclv2.SendRawTransaction(res.SignedTransaction).Do(context.Background())
   166  	if err != nil {
   167  		return err
   168  	}
   169  	waitForAlgodInDevMode()
   170  	return err
   171  }
   172  
   173  func init() {
   174  	godog.BindFlags("godog.", flag.CommandLine, &opt)
   175  }
   176  
   177  func TestMain(m *testing.M) {
   178  	flag.Parse()
   179  	opt.Paths = flag.Args()
   180  
   181  	status := godog.RunWithOptions("godogs", func(s *godog.Suite) {
   182  		FeatureContext(s)
   183  		AlgodClientV2Context(s)
   184  		IndexerUnitTestContext(s)
   185  		TransactionsUnitContext(s)
   186  		ApplicationsContext(s)
   187  		ApplicationsUnitContext(s)
   188  		ResponsesContext(s)
   189  	}, opt)
   190  
   191  	if st := m.Run(); st > status {
   192  		status = st
   193  	}
   194  	os.Exit(status)
   195  }
   196  
   197  func FeatureContext(s *godog.Suite) {
   198  	s.Step("I create a wallet", createWallet)
   199  	s.Step("the wallet should exist", walletExist)
   200  	s.Step("I get the wallet handle", getHandle)
   201  	s.Step("I can get the master derivation key", getMdk)
   202  	s.Step("I rename the wallet", renameWallet)
   203  	s.Step("I can still get the wallet information with the same handle", getWalletInfo)
   204  	s.Step("I renew the wallet handle", renewHandle)
   205  	s.Step("I release the wallet handle", releaseHandle)
   206  	s.Step("the wallet handle should not work", tryHandle)
   207  	s.Step(`payment transaction parameters (\d+) (\d+) (\d+) "([^"]*)" "([^"]*)" "([^"]*)" (\d+) "([^"]*)" "([^"]*)"`, txnParams)
   208  	s.Step(`mnemonic for private key "([^"]*)"`, mnForSk)
   209  	s.Step(`multisig addresses "([^"]*)"`, msigAddresses)
   210  	s.Step("I create the multisig payment transaction$", createMsigTxn)
   211  	s.Step("I create the multisig payment transaction with zero fee", createMsigTxnZeroFee)
   212  	s.Step("I sign the multisig transaction with the private key", signMsigTxn)
   213  	s.Step("I sign the transaction with the private key", signTxn)
   214  	s.Step(`^I add a rekeyTo field with address "([^"]*)"$`, iAddARekeyToFieldWithAddress)
   215  	s.Step(`^I add a rekeyTo field with the private key algorand address$`, iAddARekeyToFieldWithThePrivateKeyAlgorandAddress)
   216  	s.Step(`^I set the from address to "([^"]*)"$`, iSetTheFromAddressTo)
   217  	s.Step(`the signed transaction should equal the golden "([^"]*)"`, equalGolden)
   218  	s.Step(`the multisig transaction should equal the golden "([^"]*)"`, equalMsigGolden)
   219  	s.Step(`the multisig address should equal the golden "([^"]*)"`, equalMsigAddrGolden)
   220  	s.Step("I get versions with algod", aclV)
   221  	s.Step("v1 should be in the versions", v1InVersions)
   222  	s.Step("v2 should be in the versions", v2InVersions)
   223  	s.Step("I get versions with kmd", kclV)
   224  	s.Step("I import the multisig", importMsig)
   225  	s.Step("the multisig should be in the wallet", msigInWallet)
   226  	s.Step("I export the multisig", expMsig)
   227  	s.Step("the multisig should equal the exported multisig", msigEq)
   228  	s.Step("I delete the multisig", deleteMsig)
   229  	s.Step("the multisig should not be in the wallet", msigNotInWallet)
   230  	s.Step("^I generate a key using kmd for rekeying and fund it$", genRekeyKmd)
   231  	s.Step("^I generate a key using kmd$", genKeyKmd)
   232  	s.Step("the key should be in the wallet", keyInWallet)
   233  	s.Step("I delete the key", deleteKey)
   234  	s.Step("the key should not be in the wallet", keyNotInWallet)
   235  	s.Step("I generate a key", genKey)
   236  	s.Step("I import the key", importKey)
   237  	s.Step("the private key should be equal to the exported private key", skEqExport)
   238  	s.Step("a kmd client", kmdClient)
   239  	s.Step("wallet information", walletInfo)
   240  	s.Step(`default transaction with parameters (\d+) "([^"]*)"`, defaultTxn)
   241  	s.Step(`default multisig transaction with parameters (\d+) "([^"]*)"`, defaultMsigTxn)
   242  	s.Step("I get the private key", getSk)
   243  	s.Step("I send the transaction", sendTxn)
   244  	s.Step("I send the kmd-signed transaction", sendTxnKmd)
   245  	s.Step("I send the bogus kmd-signed transaction", sendTxnKmdFailureExpected)
   246  	s.Step("I send the multisig transaction", sendMsigTxn)
   247  	s.Step("the transaction should not go through", txnFail)
   248  	s.Step("I sign the transaction with kmd", signKmd)
   249  	s.Step("the signed transaction should equal the kmd signed transaction", signBothEqual)
   250  	s.Step("I sign the multisig transaction with kmd", signMsigKmd)
   251  	s.Step("the multisig transaction should equal the kmd signed multisig transaction", signMsigBothEqual)
   252  	s.Step(`^the node should be healthy`, nodeHealth)
   253  	s.Step(`^I get the ledger supply`, ledger)
   254  	s.Step(`^I create a bid`, createBid)
   255  	s.Step(`^I encode and decode the bid`, encDecBid)
   256  	s.Step(`^the bid should still be the same`, checkBid)
   257  	s.Step(`^I decode the address`, decAddr)
   258  	s.Step(`^I encode the address`, encAddr)
   259  	s.Step(`^the address should still be the same`, checkAddr)
   260  	s.Step(`^I convert the private key back to a mnemonic`, skToMn)
   261  	s.Step(`^the mnemonic should still be the same as "([^"]*)"`, checkMn)
   262  	s.Step(`^mnemonic for master derivation key "([^"]*)"`, mnToMdk)
   263  	s.Step(`^I convert the master derivation key back to a mnemonic`, mdkToMn)
   264  	s.Step(`^I create the flat fee payment transaction`, createTxnFlat)
   265  	s.Step(`^encoded multisig transaction "([^"]*)"`, encMsigTxn)
   266  	s.Step(`^I append a signature to the multisig transaction`, appendMsig)
   267  	s.Step(`^encoded multisig transactions "([^"]*)"`, encMtxs)
   268  	s.Step(`^I merge the multisig transactions`, mergeMsig)
   269  	s.Step(`^I convert (\d+) microalgos to algos and back`, microToAlgos)
   270  	s.Step(`^it should still be the same amount of microalgos (\d+)`, checkAlgos)
   271  	s.Step("I sign the bid", signBid)
   272  	s.Step(`default V2 key registration transaction "([^"]*)"`, createKeyregWithStateProof)
   273  	s.Step(`^I can get account information`, newAccInfo)
   274  	s.Step("asset test fixture", createAssetTestFixture)
   275  	s.Step(`^default asset creation transaction with total issuance (\d+)$`, defaultAssetCreateTxn)
   276  	s.Step(`^I update the asset index$`, getAssetIndex)
   277  	s.Step(`^I get the asset info$`, getAssetInfo)
   278  	s.Step(`^I should be unable to get the asset info`, failToGetAssetInfo)
   279  	s.Step(`^the asset info should match the expected asset info$`, checkExpectedVsActualAssetParams)
   280  	s.Step(`^I create a no-managers asset reconfigure transaction$`, createNoManagerAssetReconfigure)
   281  	s.Step(`^I create an asset destroy transaction$`, createAssetDestroy)
   282  	s.Step(`^I create a transaction for a second account, signalling asset acceptance$`, createAssetAcceptanceForSecondAccount)
   283  	s.Step(`^I create a transaction transferring (\d+) assets from creator to a second account$`, createAssetTransferTransactionToSecondAccount)
   284  	s.Step(`^the creator should have (\d+) assets remaining$`, theCreatorShouldHaveAssetsRemaining)
   285  	s.Step(`^I create a freeze transaction targeting the second account$`, createFreezeTransactionTargetingSecondAccount)
   286  	s.Step(`^I create a transaction transferring (\d+) assets from a second account to creator$`, createAssetTransferTransactionFromSecondAccountToCreator)
   287  	s.Step(`^I create an un-freeze transaction targeting the second account$`, createUnfreezeTransactionTargetingSecondAccount)
   288  	s.Step(`^default-frozen asset creation transaction with total issuance (\d+)$`, defaultAssetCreateTxnWithDefaultFrozen)
   289  	s.Step(`^I create a transaction revoking (\d+) assets from a second account to creator$`, createRevocationTransaction)
   290  	s.Step(`^I create a transaction transferring <amount> assets from creator to a second account$`, iCreateATransactionTransferringAmountAssetsFromCreatorToASecondAccount) // provide handler for when godog misreads
   291  	s.Step(`^base64 encoded data to sign "([^"]*)"$`, baseEncodedDataToSign)
   292  	s.Step(`^program hash "([^"]*)"$`, programHash)
   293  	s.Step(`^I perform tealsign$`, iPerformTealsign)
   294  	s.Step(`^the signature should be equal to "([^"]*)"$`, theSignatureShouldBeEqualTo)
   295  	s.Step(`^base64 encoded program "([^"]*)"$`, baseEncodedProgram)
   296  	s.Step(`^base64 encoded private key "([^"]*)"$`, baseEncodedPrivateKey)
   297  	s.Step("an algod v2 client$", algodClientV2)
   298  	s.Step("an indexer v2 client$", indexerClientV2)
   299  	s.Step(`^I compile a teal program "([^"]*)"$`, tealCompile)
   300  	s.Step(`^it is compiled with (\d+) and "([^"]*)" and "([^"]*)"$`, tealCheckCompile)
   301  	s.Step(`^base64 decoding the response is the same as the binary "([^"]*)"$`, tealCheckCompileAgainstFile)
   302  	s.Step(`^I dryrun a "([^"]*)" program "([^"]*)"$`, tealDryrun)
   303  	s.Step(`^I get execution result "([^"]*)"$`, tealCheckDryrun)
   304  	s.Step(`^I create the Method object from method signature "([^"]*)"$`, createMethodObjectFromSignature)
   305  	s.Step(`^I serialize the Method object into json$`, serializeMethodObjectIntoJson)
   306  	s.Step(`^the produced json should equal "([^"]*)" loaded from "([^"]*)"$`, checkSerializedMethodObject)
   307  	s.Step(`^I create the Method object with name "([^"]*)" first argument type "([^"]*)" second argument type "([^"]*)" and return type "([^"]*)"$`, createMethodObjectFromProperties)
   308  	s.Step(`^I create the Method object with name "([^"]*)" first argument name "([^"]*)" first argument type "([^"]*)" second argument name "([^"]*)" second argument type "([^"]*)" and return type "([^"]*)"$`, createMethodObjectWithArgNames)
   309  	s.Step(`^I create the Method object with name "([^"]*)" method description "([^"]*)" first argument type "([^"]*)" first argument description "([^"]*)" second argument type "([^"]*)" second argument description "([^"]*)" and return type "([^"]*)"$`, createMethodObjectWithDescription)
   310  	s.Step(`^the txn count should be (\d+)$`, checkTxnCount)
   311  	s.Step(`^the method selector should be "([^"]*)"$`, checkMethodSelector)
   312  	s.Step(`^I create an Interface object from the Method object with name "([^"]*)" and description "([^"]*)"$`, createInterfaceObject)
   313  	s.Step(`^I serialize the Interface object into json$`, serializeInterfaceObjectIntoJson)
   314  	s.Step(`^I create a Contract object from the Method object with name "([^"]*)" and description "([^"]*)"$`, createContractObject)
   315  	s.Step(`^I set the Contract\'s appID to (\d+) for the network "([^"]*)"$`, iSetTheContractsAppIDToForTheNetwork)
   316  	s.Step(`^I serialize the Contract object into json$`, serializeContractObjectIntoJson)
   317  	s.Step(`^the deserialized json should equal the original Method object`, deserializeMethodJson)
   318  	s.Step(`^the deserialized json should equal the original Interface object`, deserializeInterfaceJson)
   319  	s.Step(`^the deserialized json should equal the original Contract object`, deserializeContractJson)
   320  	s.Step(`^a new AtomicTransactionComposer$`, aNewAtomicTransactionComposer)
   321  	s.Step(`^suggested transaction parameters fee (\d+), flat-fee "([^"]*)", first-valid (\d+), last-valid (\d+), genesis-hash "([^"]*)", genesis-id "([^"]*)"$`, suggestedTransactionParameters)
   322  	s.Step(`^an application id (\d+)$`, anApplicationId)
   323  	s.Step(`^I make a transaction signer for the ([^"]*) account\.$`, iMakeATransactionSignerForTheAccount)
   324  	s.Step(`^I create a new method arguments array\.$`, iCreateANewMethodArgumentsArray)
   325  	s.Step(`^I append the encoded arguments "([^"]*)" to the method arguments array\.$`, iAppendTheEncodedArgumentsToTheMethodArgumentsArray)
   326  	s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments\.$`, addMethodCall)
   327  	s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments, approval-program "([^"]*)", clear-program "([^"]*)"\.$`, addMethodCallForUpdate)
   328  	s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments, approval-program "([^"]*)", clear-program "([^"]*)", global-bytes (\d+), global-ints (\d+), local-bytes (\d+), local-ints (\d+), extra-pages (\d+)\.$`, addMethodCallForCreate)
   329  	s.Step(`^I add a nonced method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments\.$`, addMethodCallWithNonce)
   330  	s.Step(`^I add the nonce "([^"]*)"$`, iAddTheNonce)
   331  	s.Step(`^I build the transaction group with the composer\. If there is an error it is "([^"]*)"\.$`, buildTheTransactionGroupWithTheComposer)
   332  	s.Step(`^The composer should have a status of "([^"]*)"\.$`, theComposerShouldHaveAStatusOf)
   333  	s.Step(`^I gather signatures with the composer\.$`, iGatherSignaturesWithTheComposer)
   334  	s.Step(`^the base64 encoded signed transactions should equal "([^"]*)"$`, theBaseEncodedSignedTransactionsShouldEqual)
   335  	s.Step(`^I build a payment transaction with sender "([^"]*)", receiver "([^"]*)", amount (\d+), close remainder to "([^"]*)"$`, iBuildAPaymentTransactionWithSenderReceiverAmountCloseRemainderTo)
   336  	s.Step(`^I create a transaction with signer with the current transaction\.$`, iCreateATransactionWithSignerWithTheCurrentTransaction)
   337  	s.Step(`^I append the current transaction with signer to the method arguments array\.$`, iAppendTheCurrentTransactionWithSignerToTheMethodArgumentsArray)
   338  	s.Step(`^a dryrun response file "([^"]*)" and a transaction at index "([^"]*)"$`, aDryrunResponseFileAndATransactionAtIndex)
   339  	s.Step(`^calling app trace produces "([^"]*)"$`, callingAppTraceProduces)
   340  	s.Step(`^I append to my Method objects list in the case of a non-empty signature "([^"]*)"$`, iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature)
   341  	s.Step(`^I create an Interface object from my Method objects list$`, iCreateAnInterfaceObjectFromMyMethodObjectsList)
   342  	s.Step(`^I create a Contract object from my Method objects list$`, iCreateAContractObjectFromMyMethodObjectsList)
   343  	s.Step(`^I get the method from the Interface by name "([^"]*)"$`, iGetTheMethodFromTheInterfaceByName)
   344  	s.Step(`^I get the method from the Contract by name "([^"]*)"$`, iGetTheMethodFromTheContractByName)
   345  	s.Step(`^the produced method signature should equal "([^"]*)"\. If there is an error it begins with "([^"]*)"$`, theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith)
   346  	s.Step(`^a source map json file "([^"]*)"$`, aSourceMapJsonFile)
   347  	s.Step(`^the string composed of pc:line number equals "([^"]*)"$`, theStringComposedOfPclineNumberEquals)
   348  	s.Step(`^I compile a teal program "([^"]*)" with mapping enabled$`, iCompileATealProgramWithMappingEnabled)
   349  	s.Step(`^the resulting source map is the same as the json "([^"]*)"$`, theResultingSourceMapIsTheSameAsTheJson)
   350  	s.Step(`^getting the line associated with a pc "([^"]*)" equals "([^"]*)"$`, gettingTheLineAssociatedWithAPcEquals)
   351  	s.Step(`^getting the last pc associated with a line "([^"]*)" equals "([^"]*)"$`, gettingTheLastPcAssociatedWithALineEquals)
   352  	s.Step(`^a base64 encoded program bytes for heuristic sanity check "([^"]*)"$`, takeB64encodedBytes)
   353  	s.Step(`^I start heuristic sanity check over the bytes$`, heuristicCheckOverBytes)
   354  	s.Step(`^if the heuristic sanity check throws an error, the error contains "([^"]*)"$`, checkErrorIfMatching)
   355  
   356  	s.BeforeScenario(func(interface{}) {
   357  		stxObj = types.SignedTxn{}
   358  		abiMethods = nil
   359  		kcl.RenewWalletHandle(handle)
   360  	})
   361  }
   362  
   363  func createWallet() error {
   364  	walletName = "Walletgo"
   365  	walletPswd = ""
   366  	resp, err := kcl.CreateWallet(walletName, walletPswd, "sqlite", types.MasterDerivationKey{})
   367  	if err != nil {
   368  		return err
   369  	}
   370  	walletID = resp.Wallet.ID
   371  	return nil
   372  }
   373  
   374  func walletExist() error {
   375  	wallets, err := kcl.ListWallets()
   376  	if err != nil {
   377  		return err
   378  	}
   379  	for _, w := range wallets.Wallets {
   380  		if w.Name == walletName {
   381  			return nil
   382  		}
   383  	}
   384  	return fmt.Errorf("Wallet not found")
   385  }
   386  
   387  func getHandle() error {
   388  	h, err := kcl.InitWalletHandle(walletID, walletPswd)
   389  	if err != nil {
   390  		return err
   391  	}
   392  	handle = h.WalletHandleToken
   393  	return nil
   394  }
   395  
   396  func getMdk() error {
   397  	_, err := kcl.ExportMasterDerivationKey(handle, walletPswd)
   398  	return err
   399  }
   400  
   401  func renameWallet() error {
   402  	walletName = "Walletgo_new"
   403  	_, err := kcl.RenameWallet(walletID, walletPswd, walletName)
   404  	return err
   405  }
   406  
   407  func getWalletInfo() error {
   408  	resp, err := kcl.GetWallet(handle)
   409  	if resp.WalletHandle.Wallet.Name != walletName {
   410  		return fmt.Errorf("Wallet name not equal")
   411  	}
   412  	return err
   413  }
   414  
   415  func renewHandle() error {
   416  	_, err := kcl.RenewWalletHandle(handle)
   417  	return err
   418  }
   419  
   420  func releaseHandle() error {
   421  	_, err := kcl.ReleaseWalletHandle(handle)
   422  	return err
   423  }
   424  
   425  func tryHandle() error {
   426  	_, err := kcl.RenewWalletHandle(handle)
   427  	if err == nil {
   428  		return fmt.Errorf("should be an error; handle was released")
   429  	}
   430  	return nil
   431  }
   432  
   433  func iAddARekeyToFieldWithThePrivateKeyAlgorandAddress() error {
   434  	pk, err := crypto.GenerateAddressFromSK(account.PrivateKey)
   435  	if err != nil {
   436  		return err
   437  	}
   438  
   439  	err = txn.Rekey(pk.String())
   440  
   441  	if err != nil {
   442  		return err
   443  	}
   444  	return nil
   445  }
   446  
   447  func txnParams(ifee, ifv, ilv int, igh, ito, iclose string, iamt int, igen, inote string) error {
   448  	var err error
   449  	if inote != "none" {
   450  		note, err = base64.StdEncoding.DecodeString(inote)
   451  		if err != nil {
   452  			return err
   453  		}
   454  	} else {
   455  		note, err = base64.StdEncoding.DecodeString("")
   456  		if err != nil {
   457  			return err
   458  		}
   459  	}
   460  	gh, err = base64.StdEncoding.DecodeString(igh)
   461  	if err != nil {
   462  		return err
   463  	}
   464  	to = ito
   465  	fee = uint64(ifee)
   466  	fv = uint64(ifv)
   467  	lv = uint64(ilv)
   468  	if iclose != "none" {
   469  		close = iclose
   470  	} else {
   471  		close = ""
   472  	}
   473  	amt = uint64(iamt)
   474  	if igen != "none" {
   475  		gen = igen
   476  	} else {
   477  		gen = ""
   478  	}
   479  	if err != nil {
   480  		return err
   481  	}
   482  	return nil
   483  }
   484  
   485  func mnForSk(mn string) error {
   486  	sk, err := mnemonic.ToPrivateKey(mn)
   487  	if err != nil {
   488  		return err
   489  	}
   490  	account.PrivateKey = sk
   491  	var buf bytes.Buffer
   492  	enc := gob.NewEncoder(&buf)
   493  	err = enc.Encode(sk.Public())
   494  	if err != nil {
   495  		return err
   496  	}
   497  	addr := buf.Bytes()[4:]
   498  
   499  	n := copy(a[:], addr)
   500  	if n != 32 {
   501  		return fmt.Errorf("wrong address bytes length")
   502  	}
   503  	return err
   504  }
   505  func msigAddresses(addresses string) error {
   506  	var err error
   507  	addrlist := strings.Fields(addresses)
   508  
   509  	var addrStructs []types.Address
   510  	for _, a := range addrlist {
   511  		addr, err := types.DecodeAddress(a)
   512  		if err != nil {
   513  			return err
   514  		}
   515  
   516  		addrStructs = append(addrStructs, addr)
   517  	}
   518  	msig, err = crypto.MultisigAccountWithParams(1, 2, addrStructs)
   519  
   520  	return err
   521  }
   522  
   523  func iSetTheFromAddressTo(address string) error {
   524  	addr, err := types.DecodeAddress(address)
   525  	if err != nil {
   526  		return err
   527  	}
   528  	txn.Sender = addr
   529  	return nil
   530  }
   531  
   532  func createMsigTxn() error {
   533  	var err error
   534  	paramsToUse := types.SuggestedParams{
   535  		Fee:             types.MicroAlgos(fee),
   536  		GenesisID:       gen,
   537  		GenesisHash:     gh,
   538  		FirstRoundValid: types.Round(fv),
   539  		LastRoundValid:  types.Round(lv),
   540  		FlatFee:         false,
   541  	}
   542  	msigaddr, _ := msig.Address()
   543  	txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse)
   544  	if err != nil {
   545  		return err
   546  	}
   547  	return err
   548  
   549  }
   550  
   551  func createMsigTxnZeroFee() error {
   552  	var err error
   553  	paramsToUse := types.SuggestedParams{
   554  		Fee:             types.MicroAlgos(fee),
   555  		GenesisID:       gen,
   556  		GenesisHash:     gh,
   557  		FirstRoundValid: types.Round(fv),
   558  		LastRoundValid:  types.Round(lv),
   559  		FlatFee:         true,
   560  	}
   561  	msigaddr, _ := msig.Address()
   562  	txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse)
   563  	if err != nil {
   564  		return err
   565  	}
   566  	return err
   567  
   568  }
   569  
   570  func signMsigTxn() error {
   571  	var err error
   572  	txid, stx, err = crypto.SignMultisigTransaction(account.PrivateKey, msig, txn)
   573  
   574  	return err
   575  }
   576  
   577  func signTxn() error {
   578  	var err error
   579  	txid, stx, err = crypto.SignTransaction(account.PrivateKey, txn)
   580  	if err != nil {
   581  		return err
   582  	}
   583  	return nil
   584  }
   585  
   586  func iAddARekeyToFieldWithAddress(address string) error {
   587  	err := txn.Rekey(address)
   588  	if err != nil {
   589  		return err
   590  	}
   591  	return nil
   592  }
   593  
   594  func equalGolden(golden string) error {
   595  	goldenDecoded, err := base64.StdEncoding.DecodeString(golden)
   596  	if err != nil {
   597  		return err
   598  	}
   599  
   600  	if !bytes.Equal(goldenDecoded, stx) {
   601  		return fmt.Errorf(base64.StdEncoding.EncodeToString(stx))
   602  	}
   603  	return nil
   604  }
   605  
   606  func equalMsigAddrGolden(golden string) error {
   607  	msigAddr, err := msig.Address()
   608  	if err != nil {
   609  		return err
   610  	}
   611  	if golden != msigAddr.String() {
   612  		return fmt.Errorf("NOT EQUAL")
   613  	}
   614  	return nil
   615  }
   616  
   617  func equalMsigGolden(golden string) error {
   618  	goldenDecoded, err := base64.StdEncoding.DecodeString(golden)
   619  	if err != nil {
   620  		return err
   621  	}
   622  	if !bytes.Equal(goldenDecoded, stx) {
   623  		return fmt.Errorf("NOT EQUAL")
   624  	}
   625  	return nil
   626  }
   627  
   628  func aclV() error {
   629  	v, err := aclv2.Versions().Do(context.Background())
   630  	if err != nil {
   631  		return err
   632  	}
   633  	versions = v.Versions
   634  	return nil
   635  }
   636  
   637  func v1InVersions() error {
   638  	for _, b := range versions {
   639  		if b == "v1" {
   640  			return nil
   641  		}
   642  	}
   643  	return fmt.Errorf("v1 not found")
   644  }
   645  
   646  func v2InVersions() error {
   647  	for _, b := range versions {
   648  		if b == "v2" {
   649  			return nil
   650  		}
   651  	}
   652  	return fmt.Errorf("v2 not found")
   653  }
   654  
   655  func kclV() error {
   656  	v, err := kcl.Version()
   657  	versions = v.Versions
   658  	return err
   659  }
   660  
   661  func importMsig() error {
   662  	_, err := kcl.ImportMultisig(handle, msig.Version, msig.Threshold, msig.Pks)
   663  	return err
   664  }
   665  
   666  func msigInWallet() error {
   667  	msigs, err := kcl.ListMultisig(handle)
   668  	if err != nil {
   669  		return err
   670  	}
   671  	addrs := msigs.Addresses
   672  	for _, a := range addrs {
   673  		addr, err := msig.Address()
   674  		if err != nil {
   675  			return err
   676  		}
   677  		if a == addr.String() {
   678  			return nil
   679  		}
   680  	}
   681  	return fmt.Errorf("msig not found")
   682  
   683  }
   684  
   685  func expMsig() error {
   686  	addr, err := msig.Address()
   687  	if err != nil {
   688  		return err
   689  	}
   690  	msigExp, err = kcl.ExportMultisig(handle, walletPswd, addr.String())
   691  
   692  	return err
   693  }
   694  
   695  func msigEq() error {
   696  	eq := true
   697  
   698  	if (msig.Pks == nil) != (msigExp.PKs == nil) {
   699  		eq = false
   700  	}
   701  
   702  	if len(msig.Pks) != len(msigExp.PKs) {
   703  		eq = false
   704  	}
   705  
   706  	for i := range msig.Pks {
   707  
   708  		if !bytes.Equal(msig.Pks[i], msigExp.PKs[i]) {
   709  			eq = false
   710  		}
   711  	}
   712  
   713  	if !eq {
   714  		return fmt.Errorf("exported msig not equal to original msig")
   715  	}
   716  	return nil
   717  }
   718  
   719  func deleteMsig() error {
   720  	addr, err := msig.Address()
   721  	kcl.DeleteMultisig(handle, walletPswd, addr.String())
   722  	return err
   723  }
   724  
   725  func msigNotInWallet() error {
   726  	msigs, err := kcl.ListMultisig(handle)
   727  	if err != nil {
   728  		return err
   729  	}
   730  	addrs := msigs.Addresses
   731  	for _, a := range addrs {
   732  		addr, err := msig.Address()
   733  		if err != nil {
   734  			return err
   735  		}
   736  		if a == addr.String() {
   737  			return fmt.Errorf("msig found unexpectedly; should have been deleted")
   738  		}
   739  	}
   740  	return nil
   741  
   742  }
   743  
   744  func genKeyKmd() error {
   745  	p, err := kcl.GenerateKey(handle)
   746  	if err != nil {
   747  		return err
   748  	}
   749  	pk = p.Address
   750  	return nil
   751  }
   752  
   753  func genRekeyKmd() error {
   754  	p, err := kcl.GenerateKey(handle)
   755  	if err != nil {
   756  		return err
   757  	}
   758  	rekey = p.Address
   759  	initializeAccount(rekey)
   760  	return nil
   761  }
   762  
   763  func keyInWallet() error {
   764  	resp, err := kcl.ListKeys(handle)
   765  	if err != nil {
   766  		return err
   767  	}
   768  	for _, a := range resp.Addresses {
   769  		if pk == a {
   770  			return nil
   771  		}
   772  	}
   773  	return fmt.Errorf("key not found")
   774  }
   775  
   776  func deleteKey() error {
   777  	_, err := kcl.DeleteKey(handle, walletPswd, pk)
   778  	return err
   779  }
   780  
   781  func keyNotInWallet() error {
   782  	resp, err := kcl.ListKeys(handle)
   783  	if err != nil {
   784  		return err
   785  	}
   786  	for _, a := range resp.Addresses {
   787  		if pk == a {
   788  			return fmt.Errorf("key found unexpectedly; should have been deleted")
   789  		}
   790  	}
   791  	return nil
   792  }
   793  
   794  func genKey() error {
   795  	account = crypto.GenerateAccount()
   796  	a = account.Address
   797  	pk = a.String()
   798  	return nil
   799  }
   800  
   801  func importKey() error {
   802  	_, err := kcl.ImportKey(handle, account.PrivateKey)
   803  	return err
   804  }
   805  
   806  func skEqExport() error {
   807  	exp, err := kcl.ExportKey(handle, walletPswd, a.String())
   808  	if err != nil {
   809  		return err
   810  	}
   811  	kcl.DeleteKey(handle, walletPswd, a.String())
   812  	if bytes.Equal(exp.PrivateKey.Seed(), account.PrivateKey.Seed()) {
   813  		return nil
   814  	}
   815  	return fmt.Errorf("private keys not equal")
   816  }
   817  
   818  func kmdClient() error {
   819  	kmdToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   820  	kmdAddress := "http://localhost:" + "60001"
   821  	var err error
   822  	kcl, err = kmd.MakeClient(kmdAddress, kmdToken)
   823  	return err
   824  }
   825  
   826  func algodClientV2() error {
   827  	algodToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   828  	algodAddress := "http://localhost:" + "60000"
   829  	var err error
   830  	aclv2, err = algodV2.MakeClient(algodAddress, algodToken)
   831  	algodV2client = aclv2
   832  	if err != nil {
   833  		return err
   834  	}
   835  	_, err = aclv2.StatusAfterBlock(1).Do(context.Background())
   836  	return err
   837  }
   838  
   839  func indexerClientV2() error {
   840  	indexerAddress := "http://localhost:" + "59999"
   841  	var err error
   842  	iclv2, err = indexerV2.MakeClient(indexerAddress, "")
   843  	indexerV2client = iclv2
   844  	return err
   845  }
   846  
   847  func walletInfo() error {
   848  	walletName = "unencrypted-default-wallet"
   849  	walletPswd = ""
   850  	wallets, err := kcl.ListWallets()
   851  	if err != nil {
   852  		return err
   853  	}
   854  	for _, w := range wallets.Wallets {
   855  		if w.Name == walletName {
   856  			walletID = w.ID
   857  		}
   858  	}
   859  	h, err := kcl.InitWalletHandle(walletID, walletPswd)
   860  	if err != nil {
   861  		return err
   862  	}
   863  	handle = h.WalletHandleToken
   864  	accs, err := kcl.ListKeys(handle)
   865  	accounts = accs.Addresses
   866  	return err
   867  }
   868  
   869  // Helper function for making default transactions.
   870  func defaultTxnWithAddress(iamt int, inote string, senderAddress string) error {
   871  	var err error
   872  	if inote != "none" {
   873  		note, err = base64.StdEncoding.DecodeString(inote)
   874  		if err != nil {
   875  			return err
   876  		}
   877  	} else {
   878  		note, err = base64.StdEncoding.DecodeString("")
   879  		if err != nil {
   880  			return err
   881  		}
   882  	}
   883  
   884  	amt = uint64(iamt)
   885  	pk = senderAddress
   886  	params, err := aclv2.SuggestedParams().Do(context.Background())
   887  	if err != nil {
   888  		return err
   889  	}
   890  	lastRound = uint64(params.FirstRoundValid)
   891  	txn, err = future.MakePaymentTxn(senderAddress, accounts[1], amt, note, "", params)
   892  	return err
   893  }
   894  
   895  func defaultTxn(iamt int, inote string) error {
   896  	return defaultTxnWithAddress(iamt, inote, accounts[0])
   897  }
   898  
   899  func defaultMsigTxn(iamt int, inote string) error {
   900  	var err error
   901  	if inote != "none" {
   902  		note, err = base64.StdEncoding.DecodeString(inote)
   903  		if err != nil {
   904  			return err
   905  		}
   906  	} else {
   907  		note, err = base64.StdEncoding.DecodeString("")
   908  		if err != nil {
   909  			return err
   910  		}
   911  	}
   912  
   913  	amt = uint64(iamt)
   914  	pk = accounts[0]
   915  
   916  	var addrStructs []types.Address
   917  	for _, a := range accounts {
   918  		addr, err := types.DecodeAddress(a)
   919  		if err != nil {
   920  			return err
   921  		}
   922  
   923  		addrStructs = append(addrStructs, addr)
   924  	}
   925  
   926  	msig, err = crypto.MultisigAccountWithParams(1, 1, addrStructs)
   927  	if err != nil {
   928  		return err
   929  	}
   930  	params, err := aclv2.SuggestedParams().Do(context.Background())
   931  	if err != nil {
   932  		return err
   933  	}
   934  	lastRound = uint64(params.FirstRoundValid)
   935  	addr, err := msig.Address()
   936  	if err != nil {
   937  		return err
   938  	}
   939  	txn, err = future.MakePaymentTxn(addr.String(), accounts[1], amt, note, "", params)
   940  	if err != nil {
   941  		return err
   942  	}
   943  	return nil
   944  }
   945  
   946  func getSk() error {
   947  	sk, err := kcl.ExportKey(handle, walletPswd, pk)
   948  	if err != nil {
   949  		return err
   950  	}
   951  	account.PrivateKey = sk.PrivateKey
   952  	return nil
   953  }
   954  
   955  func sendTxn() error {
   956  	tx, err := aclv2.SendRawTransaction(stx).Do(context.Background())
   957  	if err != nil {
   958  		return err
   959  	}
   960  	txid = tx
   961  	return nil
   962  }
   963  
   964  func sendTxnKmd() error {
   965  	var err error
   966  	txid, err = aclv2.SendRawTransaction(stxKmd).Do(context.Background())
   967  	return err
   968  }
   969  
   970  func sendTxnKmdFailureExpected() error {
   971  	tx, err := aclv2.SendRawTransaction(stxKmd).Do(context.Background())
   972  	if err == nil {
   973  		e = false
   974  		return fmt.Errorf("expected an error when sending kmd-signed transaction but no error occurred")
   975  	}
   976  	e = true
   977  	txid = tx
   978  	return nil
   979  }
   980  
   981  func sendMsigTxn() error {
   982  	_, err := aclv2.SendRawTransaction(stx).Do(context.Background())
   983  	if err != nil {
   984  		e = true
   985  	}
   986  
   987  	return nil
   988  }
   989  
   990  func txnFail() error {
   991  	if e {
   992  		return nil
   993  	}
   994  	return fmt.Errorf("sending the transaction should have failed")
   995  }
   996  
   997  func signKmd() error {
   998  	s, err := kcl.SignTransaction(handle, walletPswd, txn)
   999  	if err != nil {
  1000  		return err
  1001  	}
  1002  	stxKmd = s.SignedTransaction
  1003  	return nil
  1004  }
  1005  
  1006  func signBothEqual() error {
  1007  	if bytes.Equal(stx, stxKmd) {
  1008  		return nil
  1009  	}
  1010  	return fmt.Errorf("signed transactions not equal")
  1011  }
  1012  
  1013  func signMsigKmd() error {
  1014  	kcl.ImportMultisig(handle, msig.Version, msig.Threshold, msig.Pks)
  1015  	decoded, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(pk)
  1016  	if err != nil {
  1017  		return fmt.Errorf("signMsigKmd: %w", err)
  1018  	}
  1019  	s, err := kcl.MultisigSignTransaction(handle, walletPswd, txn, decoded[:32], types.MultisigSig{})
  1020  	if err != nil {
  1021  		return err
  1022  	}
  1023  	msgpack.Decode(s.Multisig, &msigsig)
  1024  	stxObj.Msig = msigsig
  1025  	stxObj.Sig = types.Signature{}
  1026  	stxObj.Txn = txn
  1027  	stxKmd = msgpack.Encode(stxObj)
  1028  	return nil
  1029  }
  1030  
  1031  func signMsigBothEqual() error {
  1032  	addr, err := msig.Address()
  1033  	if err != nil {
  1034  		return err
  1035  	}
  1036  	kcl.DeleteMultisig(handle, walletPswd, addr.String())
  1037  	if bytes.Equal(stx, stxKmd) {
  1038  		return nil
  1039  	}
  1040  	return fmt.Errorf("signed transactions not equal")
  1041  
  1042  }
  1043  
  1044  func nodeHealth() error {
  1045  	err := aclv2.HealthCheck().Do(context.Background())
  1046  	return err
  1047  }
  1048  
  1049  func ledger() error {
  1050  	_, err := aclv2.Supply().Do(context.Background())
  1051  	return err
  1052  }
  1053  
  1054  func createBid() error {
  1055  	var err error
  1056  	account = crypto.GenerateAccount()
  1057  	bid, err = auction.MakeBid(account.Address.String(), 1, 2, 3, account.Address.String(), 4)
  1058  	return err
  1059  }
  1060  
  1061  func encDecBid() error {
  1062  	temp := msgpack.Encode(sbid)
  1063  	err := msgpack.Decode(temp, &sbid)
  1064  	return err
  1065  }
  1066  
  1067  func signBid() error {
  1068  	signedBytes, err := crypto.SignBid(account.PrivateKey, bid)
  1069  	if err != nil {
  1070  		return err
  1071  	}
  1072  	err = msgpack.Decode(signedBytes, &sbid)
  1073  	if err != nil {
  1074  		return err
  1075  	}
  1076  	err = msgpack.Decode(signedBytes, &oldBid)
  1077  	return err
  1078  }
  1079  
  1080  func checkBid() error {
  1081  	if sbid != oldBid {
  1082  		return fmt.Errorf("bid should still be the same")
  1083  	}
  1084  	return nil
  1085  }
  1086  
  1087  func decAddr() error {
  1088  	var err error
  1089  	oldPk = pk
  1090  	a, err = types.DecodeAddress(pk)
  1091  	return err
  1092  }
  1093  
  1094  func encAddr() error {
  1095  	pk = a.String()
  1096  	return nil
  1097  }
  1098  
  1099  func checkAddr() error {
  1100  	if pk != oldPk {
  1101  		return fmt.Errorf("A decoded and encoded address should equal the original address")
  1102  	}
  1103  	return nil
  1104  }
  1105  
  1106  func skToMn() error {
  1107  	var err error
  1108  	newMn, err = mnemonic.FromPrivateKey(account.PrivateKey)
  1109  	return err
  1110  }
  1111  
  1112  func checkMn(mn string) error {
  1113  	if mn != newMn {
  1114  		return fmt.Errorf("the mnemonic should equal the original mnemonic")
  1115  	}
  1116  	return nil
  1117  }
  1118  
  1119  func mnToMdk(mn string) error {
  1120  	var err error
  1121  	mdk, err = mnemonic.ToMasterDerivationKey(mn)
  1122  	return err
  1123  }
  1124  
  1125  func mdkToMn() error {
  1126  	var err error
  1127  	newMn, err = mnemonic.FromMasterDerivationKey(mdk)
  1128  	return err
  1129  }
  1130  
  1131  func createTxnFlat() error {
  1132  	var err error
  1133  	paramsToUse := types.SuggestedParams{
  1134  		Fee:             types.MicroAlgos(fee),
  1135  		GenesisID:       gen,
  1136  		GenesisHash:     gh,
  1137  		FirstRoundValid: types.Round(fv),
  1138  		LastRoundValid:  types.Round(lv),
  1139  		FlatFee:         true,
  1140  	}
  1141  	txn, err = future.MakePaymentTxn(a.String(), to, amt, note, close, paramsToUse)
  1142  	if err != nil {
  1143  		return err
  1144  	}
  1145  	return err
  1146  }
  1147  
  1148  func encMsigTxn(encoded string) error {
  1149  	var err error
  1150  	stx, err = base64.StdEncoding.DecodeString(encoded)
  1151  	if err != nil {
  1152  		return err
  1153  	}
  1154  	err = msgpack.Decode(stx, &stxObj)
  1155  	return err
  1156  }
  1157  
  1158  func appendMsig() error {
  1159  	var err error
  1160  	msig, err = crypto.MultisigAccountFromSig(stxObj.Msig)
  1161  	if err != nil {
  1162  		return err
  1163  	}
  1164  	_, stx, err = crypto.AppendMultisigTransaction(account.PrivateKey, msig, stx)
  1165  	return err
  1166  }
  1167  
  1168  func encMtxs(txs string) error {
  1169  	var err error
  1170  	enctxs := strings.Split(txs, " ")
  1171  	bytetxs = make([][]byte, len(enctxs))
  1172  	for i := range enctxs {
  1173  		bytetxs[i], err = base64.StdEncoding.DecodeString(enctxs[i])
  1174  		if err != nil {
  1175  			return err
  1176  		}
  1177  	}
  1178  	return nil
  1179  }
  1180  
  1181  func mergeMsig() (err error) {
  1182  	_, stx, err = crypto.MergeMultisigTransactions(bytetxs...)
  1183  	return
  1184  }
  1185  
  1186  func microToAlgos(ma int) error {
  1187  	microalgos = types.MicroAlgos(ma)
  1188  	microalgos = types.ToMicroAlgos(microalgos.ToAlgos())
  1189  	return nil
  1190  }
  1191  
  1192  func checkAlgos(ma int) error {
  1193  	if types.MicroAlgos(ma) != microalgos {
  1194  		return fmt.Errorf("Converting to and from algos should not change the value")
  1195  	}
  1196  	return nil
  1197  }
  1198  
  1199  func newAccInfo() error {
  1200  	_, err := aclv2.AccountInformation(pk).Do(context.Background())
  1201  	_, _ = kcl.DeleteKey(handle, walletPswd, pk)
  1202  	return err
  1203  }
  1204  
  1205  func createKeyregWithStateProof(keyregType string) (err error) {
  1206  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1207  	if err != nil {
  1208  		return err
  1209  	}
  1210  	lastRound = uint64(params.LastRoundValid)
  1211  	pk = accounts[0]
  1212  	if keyregType == "online" {
  1213  		nonpart = false
  1214  		votekey = "9mr13Ri8rFepxN3ghIUrZNui6LqqM5hEzB45Rri5lkU="
  1215  		selkey = "dx717L3uOIIb/jr9OIyls1l5Ei00NFgRa380w7TnPr4="
  1216  		votefst = uint64(0)
  1217  		votelst = uint64(30001)
  1218  		votekd = uint64(10000)
  1219  		stateProofPK = "mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w=="
  1220  	} else if keyregType == "nonparticipation" {
  1221  		nonpart = true
  1222  		votekey = ""
  1223  		selkey = ""
  1224  		votefst = 0
  1225  		votelst = 0
  1226  		votekd = 0
  1227  		stateProofPK = ""
  1228  	} else if keyregType == "offline" {
  1229  		nonpart = false
  1230  		votekey = ""
  1231  		selkey = ""
  1232  		votefst = 0
  1233  		votelst = 0
  1234  		votekd = 0
  1235  		stateProofPK = ""
  1236  	}
  1237  
  1238  	txn, err = future.MakeKeyRegTxnWithStateProofKey(accounts[0], note, params, votekey, selkey, stateProofPK, votefst, votelst, votekd, nonpart)
  1239  	if err != nil {
  1240  		return err
  1241  	}
  1242  
  1243  	return err
  1244  }
  1245  
  1246  func createAssetTestFixture() error {
  1247  	assetTestFixture.Creator = ""
  1248  	assetTestFixture.AssetIndex = 1
  1249  	assetTestFixture.AssetName = "testcoin"
  1250  	assetTestFixture.AssetUnitName = "coins"
  1251  	assetTestFixture.AssetURL = "http://test"
  1252  	assetTestFixture.AssetMetadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh"
  1253  	assetTestFixture.ExpectedParams = modelsV2.AssetParams{}
  1254  	assetTestFixture.QueriedParams = modelsV2.AssetParams{}
  1255  	assetTestFixture.LastTransactionIssued = types.Transaction{}
  1256  	return nil
  1257  }
  1258  
  1259  func convertTransactionAssetParamsToModelsAssetParam(input types.AssetParams) modelsV2.AssetParams {
  1260  	result := modelsV2.AssetParams{
  1261  		Total:         input.Total,
  1262  		Decimals:      uint64(input.Decimals),
  1263  		DefaultFrozen: input.DefaultFrozen,
  1264  		Manager:       input.Manager.String(),
  1265  		Reserve:       input.Reserve.String(),
  1266  		Freeze:        input.Freeze.String(),
  1267  		Clawback:      input.Clawback.String(),
  1268  		UnitName:      input.UnitName,
  1269  		Name:          input.AssetName,
  1270  		Url:           input.URL,
  1271  		MetadataHash:  input.MetadataHash[:],
  1272  	}
  1273  	// input doesn't have Creator so that will remain empty
  1274  	return result
  1275  }
  1276  
  1277  func assetCreateTxnHelper(issuance int, frozenState bool) error {
  1278  	accountToUse := accounts[0]
  1279  	assetTestFixture.Creator = accountToUse
  1280  	creator := assetTestFixture.Creator
  1281  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1282  	if err != nil {
  1283  		return err
  1284  	}
  1285  	lastRound = uint64(params.FirstRoundValid)
  1286  	assetNote := []byte(nil)
  1287  	assetIssuance := uint64(issuance)
  1288  	manager := creator
  1289  	reserve := creator
  1290  	freeze := creator
  1291  	clawback := creator
  1292  	unitName := assetTestFixture.AssetUnitName
  1293  	assetName := assetTestFixture.AssetName
  1294  	url := assetTestFixture.AssetURL
  1295  	metadataHash := assetTestFixture.AssetMetadataHash
  1296  	assetCreateTxn, err := future.MakeAssetCreateTxn(creator, assetNote, params, assetIssuance, 0, frozenState, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash)
  1297  	assetTestFixture.LastTransactionIssued = assetCreateTxn
  1298  	txn = assetCreateTxn
  1299  	assetTestFixture.ExpectedParams = convertTransactionAssetParamsToModelsAssetParam(assetCreateTxn.AssetParams)
  1300  	//convertTransactionAssetParamsToModelsAssetParam leaves creator blank, repopulate
  1301  	assetTestFixture.ExpectedParams.Creator = creator
  1302  	return err
  1303  }
  1304  
  1305  func defaultAssetCreateTxn(issuance int) error {
  1306  	return assetCreateTxnHelper(issuance, false)
  1307  }
  1308  
  1309  func defaultAssetCreateTxnWithDefaultFrozen(issuance int) error {
  1310  	return assetCreateTxnHelper(issuance, true)
  1311  }
  1312  
  1313  func createNoManagerAssetReconfigure() error {
  1314  	creator := assetTestFixture.Creator
  1315  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1316  	if err != nil {
  1317  		return err
  1318  	}
  1319  	lastRound = uint64(params.FirstRoundValid)
  1320  	assetNote := []byte(nil)
  1321  	reserve := ""
  1322  	freeze := ""
  1323  	clawback := ""
  1324  	manager := creator // if this were "" as well, this wouldn't be a reconfigure txn, it would be a destroy txn
  1325  	assetReconfigureTxn, err := future.MakeAssetConfigTxn(creator, assetNote, params, assetTestFixture.AssetIndex, manager, reserve, freeze, clawback, false)
  1326  	assetTestFixture.LastTransactionIssued = assetReconfigureTxn
  1327  	txn = assetReconfigureTxn
  1328  	// update expected params
  1329  	assetTestFixture.ExpectedParams.Reserve = reserve
  1330  	assetTestFixture.ExpectedParams.Freeze = freeze
  1331  	assetTestFixture.ExpectedParams.Clawback = clawback
  1332  	return err
  1333  }
  1334  
  1335  func createAssetDestroy() error {
  1336  	creator := assetTestFixture.Creator
  1337  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1338  	if err != nil {
  1339  		return err
  1340  	}
  1341  	lastRound = uint64(params.FirstRoundValid)
  1342  	assetNote := []byte(nil)
  1343  	assetDestroyTxn, err := future.MakeAssetDestroyTxn(creator, assetNote, params, assetTestFixture.AssetIndex)
  1344  	assetTestFixture.LastTransactionIssued = assetDestroyTxn
  1345  	txn = assetDestroyTxn
  1346  	// update expected params
  1347  	assetTestFixture.ExpectedParams.Reserve = ""
  1348  	assetTestFixture.ExpectedParams.Freeze = ""
  1349  	assetTestFixture.ExpectedParams.Clawback = ""
  1350  	assetTestFixture.ExpectedParams.Manager = ""
  1351  	return err
  1352  }
  1353  
  1354  // used in getAssetIndex and similar to get the index of the most recently operated on asset
  1355  func getMaxKey(numbers []modelsV2.Asset) uint64 {
  1356  	var maxNumber uint64 = 0
  1357  	for _, asset := range numbers {
  1358  		idx := asset.Index
  1359  		if idx > maxNumber {
  1360  			maxNumber = idx
  1361  		}
  1362  	}
  1363  	return maxNumber
  1364  }
  1365  
  1366  func getAssetIndex() error {
  1367  	accountResp, err := aclv2.AccountInformation(assetTestFixture.Creator).Do(context.Background())
  1368  	if err != nil {
  1369  		return err
  1370  	}
  1371  	// get most recent asset index
  1372  	assetTestFixture.AssetIndex = getMaxKey(accountResp.CreatedAssets)
  1373  	return nil
  1374  }
  1375  
  1376  func getAssetInfo() error {
  1377  	response, err := aclv2.GetAssetByID(assetTestFixture.AssetIndex).Do(context.Background())
  1378  	assetTestFixture.QueriedParams = response.Params
  1379  	return err
  1380  }
  1381  
  1382  func failToGetAssetInfo() error {
  1383  	_, err := aclv2.GetAssetByID(assetTestFixture.AssetIndex).Do(context.Background())
  1384  	if err != nil {
  1385  		return nil
  1386  	}
  1387  	return fmt.Errorf("expected an error getting asset with index %v and creator %v, but no error was returned",
  1388  		assetTestFixture.AssetIndex, assetTestFixture.Creator)
  1389  }
  1390  
  1391  func checkExpectedVsActualAssetParams() error {
  1392  	expectedParams := assetTestFixture.ExpectedParams
  1393  	actualParams := assetTestFixture.QueriedParams
  1394  	nameMatch := expectedParams.Name == actualParams.Name
  1395  	if !nameMatch {
  1396  		return fmt.Errorf("expected asset name was %v but actual asset name was %v",
  1397  			expectedParams.Name, actualParams.Name)
  1398  	}
  1399  	unitMatch := expectedParams.UnitName == actualParams.UnitName
  1400  	if !unitMatch {
  1401  		return fmt.Errorf("expected unit name was %v but actual unit name was %v",
  1402  			expectedParams.UnitName, actualParams.UnitName)
  1403  	}
  1404  	urlMatch := expectedParams.Url == actualParams.Url
  1405  	if !urlMatch {
  1406  		return fmt.Errorf("expected URL was %v but actual URL was %v",
  1407  			expectedParams.Url, actualParams.Url)
  1408  	}
  1409  	hashMatch := reflect.DeepEqual(expectedParams.MetadataHash, actualParams.MetadataHash)
  1410  	if !hashMatch {
  1411  		return fmt.Errorf("expected MetadataHash was %v but actual MetadataHash was %v",
  1412  			expectedParams.MetadataHash, actualParams.MetadataHash)
  1413  	}
  1414  	issuanceMatch := expectedParams.Total == actualParams.Total
  1415  	if !issuanceMatch {
  1416  		return fmt.Errorf("expected total issuance was %v but actual issuance was %v",
  1417  			expectedParams.Total, actualParams.Total)
  1418  	}
  1419  	defaultFrozenMatch := expectedParams.DefaultFrozen == actualParams.DefaultFrozen
  1420  	if !defaultFrozenMatch {
  1421  		return fmt.Errorf("expected default frozen state %v but actual default frozen state was %v",
  1422  			expectedParams.DefaultFrozen, actualParams.DefaultFrozen)
  1423  	}
  1424  	managerMatch := expectedParams.Manager == actualParams.Manager
  1425  	if !managerMatch {
  1426  		return fmt.Errorf("expected asset manager was %v but actual asset manager was %v",
  1427  			expectedParams.Manager, actualParams.Manager)
  1428  	}
  1429  	reserveMatch := expectedParams.Reserve == actualParams.Reserve
  1430  	if !reserveMatch {
  1431  		return fmt.Errorf("expected asset reserve was %v but actual asset reserve was %v",
  1432  			expectedParams.Reserve, actualParams.Reserve)
  1433  	}
  1434  	freezeMatch := expectedParams.Freeze == actualParams.Freeze
  1435  	if !freezeMatch {
  1436  		return fmt.Errorf("expected freeze manager was %v but actual freeze manager was %v",
  1437  			expectedParams.Freeze, actualParams.Freeze)
  1438  	}
  1439  	clawbackMatch := expectedParams.Clawback == actualParams.Clawback
  1440  	if !clawbackMatch {
  1441  		return fmt.Errorf("expected revocation (clawback) manager was %v but actual revocation manager was %v",
  1442  			expectedParams.Clawback, actualParams.Clawback)
  1443  	}
  1444  	return nil
  1445  }
  1446  
  1447  func findAssetID(assets []modelsV2.AssetHolding, assetID uint64) (foundAsset modelsV2.AssetHolding, err error) {
  1448  	for _, asset := range assets {
  1449  		if asset.AssetId == assetID {
  1450  			return asset, nil
  1451  		}
  1452  	}
  1453  	return modelsV2.AssetHolding{}, fmt.Errorf("asset ID %d was not found", assetID)
  1454  }
  1455  
  1456  func theCreatorShouldHaveAssetsRemaining(expectedBal int) error {
  1457  	expectedBalance := uint64(expectedBal)
  1458  	accountResp, err := aclv2.AccountInformation(assetTestFixture.Creator).Do(context.Background())
  1459  	if err != nil {
  1460  		return err
  1461  	}
  1462  	// Find asset ID
  1463  	holding, err := findAssetID(accountResp.Assets, assetTestFixture.AssetIndex)
  1464  	if err != nil {
  1465  		return fmt.Errorf("attempted to get balance of account %v for creator %v and index %v, but no balance was found for that index", assetTestFixture.Creator, assetTestFixture.Creator, assetTestFixture.AssetIndex)
  1466  	}
  1467  	if holding.Amount != expectedBalance {
  1468  		return fmt.Errorf("actual balance %v differed from expected balance %v", holding.Amount, expectedBalance)
  1469  	}
  1470  	return nil
  1471  }
  1472  
  1473  func createAssetAcceptanceForSecondAccount() error {
  1474  	accountToUse := accounts[1]
  1475  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1476  	if err != nil {
  1477  		return err
  1478  	}
  1479  	lastRound = uint64(params.FirstRoundValid)
  1480  	assetNote := []byte(nil)
  1481  	assetAcceptanceTxn, err := future.MakeAssetAcceptanceTxn(accountToUse, assetNote, params, assetTestFixture.AssetIndex)
  1482  	assetTestFixture.LastTransactionIssued = assetAcceptanceTxn
  1483  	txn = assetAcceptanceTxn
  1484  	return err
  1485  }
  1486  
  1487  func createAssetTransferTransactionToSecondAccount(amount int) error {
  1488  	recipient := accounts[1]
  1489  	creator := assetTestFixture.Creator
  1490  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1491  	if err != nil {
  1492  		return err
  1493  	}
  1494  	sendAmount := uint64(amount)
  1495  	closeAssetsTo := ""
  1496  	lastRound = uint64(params.FirstRoundValid)
  1497  	assetNote := []byte(nil)
  1498  	assetAcceptanceTxn, err := future.MakeAssetTransferTxn(creator, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex)
  1499  	assetTestFixture.LastTransactionIssued = assetAcceptanceTxn
  1500  	txn = assetAcceptanceTxn
  1501  	return err
  1502  }
  1503  
  1504  func createAssetTransferTransactionFromSecondAccountToCreator(amount int) error {
  1505  	recipient := assetTestFixture.Creator
  1506  	sender := accounts[1]
  1507  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1508  	if err != nil {
  1509  		return err
  1510  	}
  1511  	sendAmount := uint64(amount)
  1512  	closeAssetsTo := ""
  1513  	lastRound = uint64(params.FirstRoundValid)
  1514  	assetNote := []byte(nil)
  1515  	assetAcceptanceTxn, err := future.MakeAssetTransferTxn(sender, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex)
  1516  	assetTestFixture.LastTransactionIssued = assetAcceptanceTxn
  1517  	txn = assetAcceptanceTxn
  1518  	return err
  1519  }
  1520  
  1521  // sets up a freeze transaction, with freeze state `setting` against target account `target`
  1522  // assumes creator is asset freeze manager
  1523  func freezeTransactionHelper(target string, setting bool) error {
  1524  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1525  	if err != nil {
  1526  		return err
  1527  	}
  1528  	lastRound = uint64(params.FirstRoundValid)
  1529  	assetNote := []byte(nil)
  1530  	assetFreezeOrUnfreezeTxn, err := future.MakeAssetFreezeTxn(assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex, target, setting)
  1531  	assetTestFixture.LastTransactionIssued = assetFreezeOrUnfreezeTxn
  1532  	txn = assetFreezeOrUnfreezeTxn
  1533  	return err
  1534  }
  1535  
  1536  func createFreezeTransactionTargetingSecondAccount() error {
  1537  	return freezeTransactionHelper(accounts[1], true)
  1538  }
  1539  
  1540  func createUnfreezeTransactionTargetingSecondAccount() error {
  1541  	return freezeTransactionHelper(accounts[1], false)
  1542  }
  1543  
  1544  func createRevocationTransaction(amount int) error {
  1545  	params, err := aclv2.SuggestedParams().Do(context.Background())
  1546  	if err != nil {
  1547  		return err
  1548  	}
  1549  	lastRound = uint64(params.FirstRoundValid)
  1550  	revocationAmount := uint64(amount)
  1551  	assetNote := []byte(nil)
  1552  	assetRevokeTxn, err := future.MakeAssetRevocationTxn(assetTestFixture.Creator, accounts[1], revocationAmount, assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex)
  1553  	assetTestFixture.LastTransactionIssued = assetRevokeTxn
  1554  	txn = assetRevokeTxn
  1555  	return err
  1556  }
  1557  
  1558  // godog misreads the step for this function, so provide a handler for when it does so
  1559  func iCreateATransactionTransferringAmountAssetsFromCreatorToASecondAccount() error {
  1560  	return createAssetTransferTransactionToSecondAccount(500000)
  1561  }
  1562  
  1563  func baseEncodedDataToSign(dataEnc string) (err error) {
  1564  	data, err = base64.StdEncoding.DecodeString(dataEnc)
  1565  	return
  1566  }
  1567  
  1568  func programHash(addr string) (err error) {
  1569  	account.Address, err = types.DecodeAddress(addr)
  1570  	return
  1571  }
  1572  
  1573  func iPerformTealsign() (err error) {
  1574  	sig, err = crypto.TealSign(account.PrivateKey, data, account.Address)
  1575  	return
  1576  }
  1577  
  1578  func theSignatureShouldBeEqualTo(sigEnc string) error {
  1579  	expected, err := base64.StdEncoding.DecodeString(sigEnc)
  1580  	if err != nil {
  1581  		return err
  1582  	}
  1583  	if !bytes.Equal(expected, sig[:]) {
  1584  		return fmt.Errorf("%v != %v", expected, sig[:])
  1585  	}
  1586  	return nil
  1587  }
  1588  
  1589  func baseEncodedProgram(programEnc string) error {
  1590  	program, err := base64.StdEncoding.DecodeString(programEnc)
  1591  	if err != nil {
  1592  		return err
  1593  	}
  1594  	account.Address = crypto.AddressFromProgram(program)
  1595  	return nil
  1596  }
  1597  
  1598  func baseEncodedPrivateKey(skEnc string) error {
  1599  	seed, err := base64.StdEncoding.DecodeString(skEnc)
  1600  	if err != nil {
  1601  		return err
  1602  	}
  1603  	account.PrivateKey = ed25519.NewKeyFromSeed(seed)
  1604  	return nil
  1605  }
  1606  
  1607  func tealCompile(filename string) (err error) {
  1608  	if len(filename) == 0 {
  1609  		return fmt.Errorf("empty teal program file name")
  1610  	}
  1611  	tealProgram, err := loadResource(filename)
  1612  	if err != nil {
  1613  		return err
  1614  	}
  1615  	result, err := aclv2.TealCompile(tealProgram).Do(context.Background())
  1616  	if err == nil {
  1617  		tealCompleResult.status = 200
  1618  		tealCompleResult.response = result
  1619  		return
  1620  	}
  1621  	if _, ok := err.(commonV2.BadRequest); ok {
  1622  		tealCompleResult.status = 400
  1623  		tealCompleResult.response.Hash = ""
  1624  		tealCompleResult.response.Result = ""
  1625  		return nil
  1626  	}
  1627  
  1628  	return
  1629  }
  1630  
  1631  func tealCheckCompile(status int, result string, hash string) error {
  1632  	if status != tealCompleResult.status {
  1633  		return fmt.Errorf("status: %d != %d", status, tealCompleResult.status)
  1634  	}
  1635  	if result != tealCompleResult.response.Result {
  1636  		return fmt.Errorf("result: %s != %s", result, tealCompleResult.response.Result)
  1637  	}
  1638  
  1639  	if hash != tealCompleResult.response.Hash {
  1640  		return fmt.Errorf("hash: %s != %s", hash, tealCompleResult.response.Hash)
  1641  	}
  1642  	return nil
  1643  }
  1644  
  1645  func tealCheckCompileAgainstFile(expectedFile string) error {
  1646  	if len(expectedFile) == 0 {
  1647  		return fmt.Errorf("empty teal program file name")
  1648  	}
  1649  
  1650  	expectedTeal, err := loadResource(expectedFile)
  1651  	if err != nil {
  1652  		return err
  1653  	}
  1654  
  1655  	actualTeal, err := base64.StdEncoding.DecodeString(tealCompleResult.response.Result)
  1656  	if err != nil {
  1657  		return err
  1658  	}
  1659  
  1660  	if !bytes.Equal(actualTeal, expectedTeal) {
  1661  		return fmt.Errorf("Actual program does not match expected")
  1662  	}
  1663  
  1664  	return nil
  1665  }
  1666  
  1667  func tealDryrun(kind string, filename string) (err error) {
  1668  	if len(filename) == 0 {
  1669  		return fmt.Errorf("empty teal program file name")
  1670  	}
  1671  	tealProgram, err := loadResource(filename)
  1672  	if err != nil {
  1673  		return err
  1674  	}
  1675  
  1676  	txns := []types.SignedTxn{{}}
  1677  	sources := []modelsV2.DryrunSource{}
  1678  	switch kind {
  1679  	case "compiled":
  1680  		txns[0].Lsig.Logic = tealProgram
  1681  	case "source":
  1682  		sources = append(sources, modelsV2.DryrunSource{
  1683  			FieldName: "lsig",
  1684  			Source:    string(tealProgram),
  1685  			TxnIndex:  0,
  1686  		})
  1687  	default:
  1688  		return fmt.Errorf("kind %s not in (source, compiled)", kind)
  1689  	}
  1690  
  1691  	ddr := modelsV2.DryrunRequest{
  1692  		Txns:    txns,
  1693  		Sources: sources,
  1694  	}
  1695  
  1696  	result, err := aclv2.TealDryrun(ddr).Do(context.Background())
  1697  	if err != nil {
  1698  		return
  1699  	}
  1700  
  1701  	tealDryrunResult.response = result
  1702  	return
  1703  }
  1704  
  1705  func tealCheckDryrun(result string) error {
  1706  	txnResult := tealDryrunResult.response.Txns[0]
  1707  	var msgs []string
  1708  	if txnResult.AppCallMessages != nil && len(txnResult.AppCallMessages) > 0 {
  1709  		msgs = txnResult.AppCallMessages
  1710  	} else if txnResult.LogicSigMessages != nil && len(txnResult.LogicSigMessages) > 0 {
  1711  		msgs = txnResult.LogicSigMessages
  1712  	}
  1713  	if len(msgs) == 0 {
  1714  		return fmt.Errorf("received no messages")
  1715  	}
  1716  
  1717  	if msgs[len(msgs)-1] != result {
  1718  		return fmt.Errorf("dryrun status %s != %s", result, msgs[len(msgs)-1])
  1719  	}
  1720  	return nil
  1721  }
  1722  
  1723  func createMethodObjectFromSignature(methodSig string) error {
  1724  	abiMethodLocal, err := abi.MethodFromSignature(methodSig)
  1725  	abiMethod = abiMethodLocal
  1726  	return err
  1727  }
  1728  
  1729  func serializeMethodObjectIntoJson() error {
  1730  	abiMethodJson, err := json.Marshal(abiMethod)
  1731  	if err != nil {
  1732  		return err
  1733  	}
  1734  
  1735  	abiJsonString = string(abiMethodJson)
  1736  	return nil
  1737  }
  1738  
  1739  func checkSerializedMethodObject(jsonFile, loadedFrom string) error {
  1740  	directory := path.Join("./features/unit/", loadedFrom)
  1741  	jsons, err := loadMockJsons(jsonFile, directory)
  1742  	if err != nil {
  1743  		return err
  1744  	}
  1745  	correctJson := string(jsons[0])
  1746  
  1747  	var actualJson interface{}
  1748  	err = json.Unmarshal([]byte(abiJsonString), &actualJson)
  1749  	if err != nil {
  1750  		return err
  1751  	}
  1752  
  1753  	var expectedJson interface{}
  1754  	err = json.Unmarshal([]byte(correctJson), &expectedJson)
  1755  	if err != nil {
  1756  		return err
  1757  	}
  1758  
  1759  	if !reflect.DeepEqual(actualJson, expectedJson) {
  1760  		return fmt.Errorf("json strings %s != %s", correctJson, abiJsonString)
  1761  	}
  1762  
  1763  	return nil
  1764  }
  1765  
  1766  func createMethodObjectFromProperties(name, firstArgType, secondArgType, returnType string) error {
  1767  	args := []abi.Arg{
  1768  		{Name: "", Type: firstArgType, Desc: ""},
  1769  		{Name: "", Type: secondArgType, Desc: ""},
  1770  	}
  1771  	abiMethod = abi.Method{
  1772  		Name:    name,
  1773  		Desc:    "",
  1774  		Args:    args,
  1775  		Returns: abi.Return{Type: returnType, Desc: ""},
  1776  	}
  1777  	return nil
  1778  }
  1779  
  1780  func createMethodObjectWithArgNames(name, firstArgName, firstArgType, secondArgName, secondArgType, returnType string) error {
  1781  	args := []abi.Arg{
  1782  		{Name: firstArgName, Type: firstArgType, Desc: ""},
  1783  		{Name: secondArgName, Type: secondArgType, Desc: ""},
  1784  	}
  1785  	abiMethod = abi.Method{
  1786  		Name:    name,
  1787  		Desc:    "",
  1788  		Args:    args,
  1789  		Returns: abi.Return{Type: returnType, Desc: ""},
  1790  	}
  1791  	return nil
  1792  }
  1793  
  1794  func createMethodObjectWithDescription(name, nameDesc, firstArgType, firstDesc, secondArgType, secondDesc, returnType string) error {
  1795  	args := []abi.Arg{
  1796  		{Name: "", Type: firstArgType, Desc: firstDesc},
  1797  		{Name: "", Type: secondArgType, Desc: secondDesc},
  1798  	}
  1799  	abiMethod = abi.Method{
  1800  		Name:    name,
  1801  		Desc:    nameDesc,
  1802  		Args:    args,
  1803  		Returns: abi.Return{Type: returnType, Desc: ""},
  1804  	}
  1805  	return nil
  1806  }
  1807  
  1808  func checkTxnCount(givenTxnCount int) error {
  1809  	correctTxnCount := abiMethod.GetTxCount()
  1810  	if correctTxnCount != givenTxnCount {
  1811  		return fmt.Errorf("txn count %d != %d", givenTxnCount, correctTxnCount)
  1812  	}
  1813  	return nil
  1814  }
  1815  
  1816  func checkMethodSelector(givenMethodSelector string) error {
  1817  	correctMethodSelector := hex.EncodeToString(abiMethod.GetSelector())
  1818  	if correctMethodSelector != givenMethodSelector {
  1819  		return fmt.Errorf("method selector %s != %s", givenMethodSelector, correctMethodSelector)
  1820  	}
  1821  	return nil
  1822  }
  1823  
  1824  func createInterfaceObject(name string, desc string) error {
  1825  	abiInterface = abi.Interface{
  1826  		Name:    name,
  1827  		Desc:    desc,
  1828  		Methods: []abi.Method{abiMethod},
  1829  	}
  1830  	return nil
  1831  }
  1832  
  1833  func serializeInterfaceObjectIntoJson() error {
  1834  	abiInterfaceJson, err := json.Marshal(abiInterface)
  1835  	if err != nil {
  1836  		return err
  1837  	}
  1838  
  1839  	abiJsonString = string(abiInterfaceJson)
  1840  	return nil
  1841  }
  1842  
  1843  func createContractObject(name string, desc string) error {
  1844  	abiContract = abi.Contract{
  1845  		Name:     name,
  1846  		Desc:     desc,
  1847  		Networks: make(map[string]abi.ContractNetworkInfo),
  1848  		Methods:  []abi.Method{abiMethod},
  1849  	}
  1850  	return nil
  1851  }
  1852  
  1853  func iSetTheContractsAppIDToForTheNetwork(appID int, network string) error {
  1854  	if appID < 0 {
  1855  		return fmt.Errorf("App ID must not be negative. Got: %d", appID)
  1856  	}
  1857  	abiContract.Networks[network] = abi.ContractNetworkInfo{AppID: uint64(appID)}
  1858  	return nil
  1859  }
  1860  
  1861  func serializeContractObjectIntoJson() error {
  1862  	abiContractJson, err := json.Marshal(abiContract)
  1863  	if err != nil {
  1864  		return err
  1865  	}
  1866  
  1867  	abiJsonString = string(abiContractJson)
  1868  	return nil
  1869  }
  1870  
  1871  func iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature(arg1 string) error {
  1872  	if arg1 == "" {
  1873  		return nil
  1874  	}
  1875  
  1876  	meth, err := abi.MethodFromSignature(arg1)
  1877  	abiMethods = append(abiMethods, meth)
  1878  	return err
  1879  }
  1880  
  1881  func iCreateAnInterfaceObjectFromMyMethodObjectsList() error {
  1882  	abiInterface = abi.Interface{
  1883  		Name:    "",
  1884  		Methods: abiMethods,
  1885  	}
  1886  	return nil
  1887  }
  1888  
  1889  func iGetTheMethodFromTheInterfaceByName(arg1 string) error {
  1890  	abiMethod, globalErrForExamination = abiInterface.GetMethodByName(arg1)
  1891  	return nil
  1892  }
  1893  
  1894  func iCreateAContractObjectFromMyMethodObjectsList() error {
  1895  	abiContract = abi.Contract{
  1896  		Name:    "",
  1897  		Methods: abiMethods,
  1898  	}
  1899  	return nil
  1900  }
  1901  
  1902  func iGetTheMethodFromTheContractByName(arg1 string) error {
  1903  	abiMethod, globalErrForExamination = abiContract.GetMethodByName(arg1)
  1904  	return nil
  1905  }
  1906  
  1907  func theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith(arg1, arg2 string) error {
  1908  	if abiMethod.Name != "" {
  1909  		if arg2 != "" {
  1910  			return fmt.Errorf("expected error condition but got a method")
  1911  		}
  1912  		if arg1 != abiMethod.GetSignature() {
  1913  			return fmt.Errorf("signature mismatch: %s != %s", arg1, abiMethod.GetSignature())
  1914  		}
  1915  	} else if globalErrForExamination != nil {
  1916  		if arg2 == "" {
  1917  			return fmt.Errorf("got error %s, expected no error", globalErrForExamination)
  1918  		}
  1919  
  1920  		if !strings.Contains(globalErrForExamination.Error(), arg2) {
  1921  			return fmt.Errorf("produced error does not match expected: %q does not contain %q", globalErrForExamination.Error(), arg2)
  1922  		}
  1923  
  1924  	} else {
  1925  		return fmt.Errorf("both abi method and error string are empty")
  1926  	}
  1927  
  1928  	return nil
  1929  }
  1930  
  1931  // equality helper methods
  1932  func checkEqualMethods(method1, method2 abi.Method) bool {
  1933  	if method1.Name != method2.Name || method1.Desc != method2.Desc {
  1934  		return false
  1935  	}
  1936  
  1937  	if method1.Returns.Type != method2.Returns.Type || method1.Returns.Desc != method2.Returns.Desc {
  1938  		return false
  1939  	}
  1940  
  1941  	if len(method1.Args) != len(method2.Args) {
  1942  		return false
  1943  	}
  1944  
  1945  	for i, arg1 := range method1.Args {
  1946  		arg2 := method2.Args[i]
  1947  		if arg1.Name != arg2.Name || arg1.Type != arg2.Type || arg1.Desc != arg2.Desc {
  1948  			return false
  1949  		}
  1950  	}
  1951  	return true
  1952  }
  1953  
  1954  func checkEqualInterfaces(interface1, interface2 abi.Interface) bool {
  1955  	if interface1.Name != interface2.Name || interface1.Desc != interface2.Desc {
  1956  		return false
  1957  	}
  1958  
  1959  	if len(interface1.Methods) != len(interface2.Methods) {
  1960  		return false
  1961  	}
  1962  
  1963  	for i, method := range interface1.Methods {
  1964  		if !checkEqualMethods(method, interface2.Methods[i]) {
  1965  			return false
  1966  		}
  1967  	}
  1968  	return true
  1969  }
  1970  
  1971  func checkEqualContracts(contract1, contract2 abi.Contract) bool {
  1972  	if contract1.Name != contract2.Name || contract1.Desc != contract2.Desc {
  1973  		return false
  1974  	}
  1975  
  1976  	if len(contract1.Networks) != len(contract2.Networks) {
  1977  		return false
  1978  	}
  1979  
  1980  	for network, info1 := range contract1.Networks {
  1981  		info2, ok := contract2.Networks[network]
  1982  		if !ok || info1 != info2 {
  1983  			return false
  1984  		}
  1985  	}
  1986  
  1987  	if len(contract1.Methods) != len(contract2.Methods) {
  1988  		return false
  1989  	}
  1990  
  1991  	for i, method := range contract1.Methods {
  1992  		if !checkEqualMethods(method, contract2.Methods[i]) {
  1993  			return false
  1994  		}
  1995  	}
  1996  	return true
  1997  }
  1998  
  1999  func deserializeMethodJson() error {
  2000  	var deserializedMethod abi.Method
  2001  	err := json.Unmarshal([]byte(abiJsonString), &deserializedMethod)
  2002  	if err != nil {
  2003  		return err
  2004  	}
  2005  
  2006  	if !checkEqualMethods(deserializedMethod, abiMethod) {
  2007  		return fmt.Errorf("Deserialized method does not match original method")
  2008  	}
  2009  	return nil
  2010  }
  2011  
  2012  func deserializeInterfaceJson() error {
  2013  	var deserializedInterface abi.Interface
  2014  	err := json.Unmarshal([]byte(abiJsonString), &deserializedInterface)
  2015  	if err != nil {
  2016  		return err
  2017  	}
  2018  	if !checkEqualInterfaces(deserializedInterface, abiInterface) {
  2019  		return fmt.Errorf("Deserialized interface does not match original interface")
  2020  	}
  2021  	return nil
  2022  }
  2023  
  2024  func deserializeContractJson() error {
  2025  	var deserializedContract abi.Contract
  2026  	err := json.Unmarshal([]byte(abiJsonString), &deserializedContract)
  2027  	if err != nil {
  2028  		return err
  2029  	}
  2030  	if !checkEqualContracts(deserializedContract, abiContract) {
  2031  		return fmt.Errorf("Deserialized contract does not match original contract")
  2032  	}
  2033  	return nil
  2034  }
  2035  
  2036  func aNewAtomicTransactionComposer() error {
  2037  	txComposer = future.AtomicTransactionComposer{}
  2038  	return nil
  2039  }
  2040  
  2041  func suggestedTransactionParameters(fee int, flatFee string, firstValid, LastValid int, genesisHash, genesisId string) error {
  2042  	if flatFee != "true" && flatFee != "false" {
  2043  		return fmt.Errorf("flatFee must be either 'true' or 'false'")
  2044  	}
  2045  
  2046  	genHash, err := base64.StdEncoding.DecodeString(genesisHash)
  2047  	if err != nil {
  2048  		return err
  2049  	}
  2050  
  2051  	sugParams = types.SuggestedParams{
  2052  		Fee:             types.MicroAlgos(fee),
  2053  		GenesisID:       genesisId,
  2054  		GenesisHash:     genHash,
  2055  		FirstRoundValid: types.Round(firstValid),
  2056  		LastRoundValid:  types.Round(LastValid),
  2057  		FlatFee:         flatFee == "true",
  2058  	}
  2059  
  2060  	return nil
  2061  }
  2062  
  2063  func anApplicationId(id int) error {
  2064  	if id < 0 {
  2065  		return fmt.Errorf("app id must be positive integer")
  2066  	}
  2067  
  2068  	applicationId = uint64(id)
  2069  	return nil
  2070  }
  2071  
  2072  func iMakeATransactionSignerForTheAccount(accountType string) error {
  2073  	if accountType == "signing" {
  2074  		accountTxSigner = future.BasicAccountTransactionSigner{
  2075  			Account: account,
  2076  		}
  2077  	} else if accountType == "transient" {
  2078  		accountTxSigner = future.BasicAccountTransactionSigner{
  2079  			Account: transientAccount,
  2080  		}
  2081  	}
  2082  
  2083  	return nil
  2084  }
  2085  
  2086  func iCreateANewMethodArgumentsArray() error {
  2087  	methodArgs = make([]interface{}, 0)
  2088  	return nil
  2089  }
  2090  
  2091  func iAppendTheEncodedArgumentsToTheMethodArgumentsArray(commaSeparatedB64Args string) error {
  2092  	if len(commaSeparatedB64Args) == 0 {
  2093  		return nil
  2094  	}
  2095  
  2096  	b64Args := strings.Split(commaSeparatedB64Args, ",")
  2097  	for _, b64Arg := range b64Args {
  2098  		if strings.Contains(b64Arg, ":") {
  2099  			// special case for inserting existing application ID
  2100  			parts := strings.Split(b64Arg, ":")
  2101  			if len(parts) != 2 || parts[0] != "ctxAppIdx" {
  2102  				return fmt.Errorf("Cannot process argument: %s", b64Arg)
  2103  			}
  2104  			parsedIndex, err := strconv.ParseUint(parts[1], 10, 64)
  2105  			if err != nil {
  2106  				return err
  2107  			}
  2108  			if parsedIndex >= uint64(len(applicationIds)) {
  2109  				return fmt.Errorf("Application index out of bounds: %d, number of app IDs is %d", parsedIndex, len(applicationIds))
  2110  			}
  2111  			abiUint64, err := abi.TypeOf("uint64")
  2112  			if err != nil {
  2113  				return err
  2114  			}
  2115  			encodedUint64, err := abiUint64.Encode(applicationIds[parsedIndex])
  2116  			if err != nil {
  2117  				return err
  2118  			}
  2119  			methodArgs = append(methodArgs, encodedUint64)
  2120  			continue
  2121  		}
  2122  		decodedArg, err := base64.StdEncoding.DecodeString(b64Arg)
  2123  		if err != nil {
  2124  			return err
  2125  		}
  2126  		methodArgs = append(methodArgs, decodedArg)
  2127  	}
  2128  
  2129  	return nil
  2130  }
  2131  
  2132  func addMethodCall(accountType, strOnComplete string) error {
  2133  	return addMethodCallHelper(accountType, strOnComplete, "", "", 0, 0, 0, 0, 0, false)
  2134  }
  2135  
  2136  func addMethodCallForUpdate(accountType, strOnComplete, approvalProgram, clearProgram string) error {
  2137  	return addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram, 0, 0, 0, 0, 0, false)
  2138  }
  2139  
  2140  func addMethodCallForCreate(accountType, strOnComplete, approvalProgram, clearProgram string, globalBytes, globalInts, localBytes, localInts, extraPages int) error {
  2141  	return addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram, globalBytes, globalInts, localBytes, localInts, extraPages, false)
  2142  }
  2143  
  2144  func addMethodCallWithNonce(accountType, strOnComplete string) error {
  2145  	return addMethodCallHelper(accountType, strOnComplete, "", "", 0, 0, 0, 0, 0, true)
  2146  }
  2147  
  2148  func addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram string, globalBytes, globalInts, localBytes, localInts, extraPages int, useNonce bool) error {
  2149  	var onComplete types.OnCompletion
  2150  	switch strOnComplete {
  2151  	case "create":
  2152  		onComplete = types.NoOpOC
  2153  	case "noop":
  2154  		onComplete = types.NoOpOC
  2155  	case "update":
  2156  		onComplete = types.UpdateApplicationOC
  2157  	case "call":
  2158  		onComplete = types.NoOpOC
  2159  	case "optin":
  2160  		onComplete = types.OptInOC
  2161  	case "clear":
  2162  		onComplete = types.ClearStateOC
  2163  	case "closeout":
  2164  		onComplete = types.CloseOutOC
  2165  	case "delete":
  2166  		onComplete = types.DeleteApplicationOC
  2167  	default:
  2168  		return fmt.Errorf("invalid onComplete value")
  2169  	}
  2170  
  2171  	var useAccount crypto.Account
  2172  	if accountType == "signing" {
  2173  		useAccount = account
  2174  	} else if accountType == "transient" {
  2175  		useAccount = transientAccount
  2176  	}
  2177  
  2178  	var approvalProgramBytes []byte
  2179  	var clearProgramBytes []byte
  2180  	var err error
  2181  
  2182  	if approvalProgram != "" {
  2183  		approvalProgramBytes, err = readTealProgram(approvalProgram)
  2184  		if err != nil {
  2185  			return err
  2186  		}
  2187  	}
  2188  
  2189  	if clearProgram != "" {
  2190  		clearProgramBytes, err = readTealProgram(clearProgram)
  2191  		if err != nil {
  2192  			return err
  2193  		}
  2194  	}
  2195  
  2196  	if globalInts < 0 || globalBytes < 0 || localInts < 0 || localBytes < 0 || extraPages < 0 {
  2197  		return fmt.Errorf("Values for globalInts, globalBytes, localInts, localBytes, and extraPages cannot be negative")
  2198  	}
  2199  
  2200  	// populate args from methodArgs
  2201  	if len(methodArgs) != len(abiMethod.Args) {
  2202  		return fmt.Errorf("Provided argument count is incorrect. Expected %d, got %d", len(abiMethod.Args), len(methodArgs))
  2203  	}
  2204  
  2205  	var preparedArgs []interface{}
  2206  	for i, argSpec := range abiMethod.Args {
  2207  		if argSpec.IsTransactionArg() {
  2208  			// encodedArg is already a TransactionWithSigner
  2209  			preparedArgs = append(preparedArgs, methodArgs[i])
  2210  			continue
  2211  		}
  2212  
  2213  		encodedArg, ok := methodArgs[i].([]byte)
  2214  		if !ok {
  2215  			return fmt.Errorf("Argument should be a byte slice")
  2216  		}
  2217  
  2218  		var typeToDecode abi.Type
  2219  		var err error
  2220  
  2221  		if argSpec.IsReferenceArg() {
  2222  			switch argSpec.Type {
  2223  			case abi.AccountReferenceType:
  2224  				typeToDecode, err = abi.TypeOf("address")
  2225  			case abi.ApplicationReferenceType, abi.AssetReferenceType:
  2226  				typeToDecode, err = abi.TypeOf("uint64")
  2227  			default:
  2228  				return fmt.Errorf("Unknown reference type: %s", argSpec.Type)
  2229  			}
  2230  		} else {
  2231  			typeToDecode, err = argSpec.GetTypeObject()
  2232  		}
  2233  		if err != nil {
  2234  			return err
  2235  		}
  2236  
  2237  		decodedArg, err := typeToDecode.Decode(encodedArg)
  2238  		if err != nil {
  2239  			return err
  2240  		}
  2241  
  2242  		preparedArgs = append(preparedArgs, decodedArg)
  2243  	}
  2244  
  2245  	methodCallParams := future.AddMethodCallParams{
  2246  		AppID:           applicationId,
  2247  		Method:          abiMethod,
  2248  		MethodArgs:      preparedArgs,
  2249  		Sender:          useAccount.Address,
  2250  		SuggestedParams: sugParams,
  2251  		OnComplete:      onComplete,
  2252  		ApprovalProgram: approvalProgramBytes,
  2253  		ClearProgram:    clearProgramBytes,
  2254  		GlobalSchema: types.StateSchema{
  2255  			NumUint:      uint64(globalInts),
  2256  			NumByteSlice: uint64(globalBytes),
  2257  		},
  2258  		LocalSchema: types.StateSchema{
  2259  			NumUint:      uint64(localInts),
  2260  			NumByteSlice: uint64(localBytes),
  2261  		},
  2262  		ExtraPages: uint32(extraPages),
  2263  		Signer:     accountTxSigner,
  2264  	}
  2265  
  2266  	if useNonce {
  2267  		methodCallParams.Note = note
  2268  	}
  2269  
  2270  	return txComposer.AddMethodCall(methodCallParams)
  2271  }
  2272  
  2273  func iAddTheNonce(nonce string) error {
  2274  	note = []byte("I should be unique thanks to this nonce: " + nonce)
  2275  	return nil
  2276  }
  2277  
  2278  func buildTheTransactionGroupWithTheComposer(errorType string) error {
  2279  	_, err := txComposer.BuildGroup()
  2280  
  2281  	switch errorType {
  2282  	case "":
  2283  		// no error expected
  2284  		return err
  2285  	case "zero group size error":
  2286  		if err == nil || err.Error() != "attempting to build group with zero transactions" {
  2287  			return fmt.Errorf("Expected error, but got: %v", err)
  2288  		}
  2289  		return nil
  2290  	default:
  2291  		return fmt.Errorf("Unknown error type: %s", errorType)
  2292  	}
  2293  }
  2294  
  2295  func theComposerShouldHaveAStatusOf(strStatus string) error {
  2296  	var status future.AtomicTransactionComposerStatus
  2297  	switch strStatus {
  2298  	case "BUILDING":
  2299  		status = future.BUILDING
  2300  	case "BUILT":
  2301  		status = future.BUILT
  2302  	case "SIGNED":
  2303  		status = future.SIGNED
  2304  	case "SUBMITTED":
  2305  		status = future.SUBMITTED
  2306  	case "COMMITTED":
  2307  		status = future.COMMITTED
  2308  	default:
  2309  		return fmt.Errorf("invalid status provided")
  2310  	}
  2311  
  2312  	if status != txComposer.GetStatus() {
  2313  		return fmt.Errorf("status does not match")
  2314  	}
  2315  
  2316  	return nil
  2317  }
  2318  
  2319  func iGatherSignaturesWithTheComposer() error {
  2320  	signedTxs, err := txComposer.GatherSignatures()
  2321  	sigTxs = signedTxs
  2322  	return err
  2323  }
  2324  
  2325  func theBaseEncodedSignedTransactionsShouldEqual(encodedTxsStr string) error {
  2326  	encodedTxs := strings.Split(encodedTxsStr, ",")
  2327  	if len(encodedTxs) != len(sigTxs) {
  2328  		return fmt.Errorf("Actual and expected number of signed transactions don't match")
  2329  	}
  2330  
  2331  	for i, encodedTx := range encodedTxs {
  2332  		gold, err := base64.StdEncoding.DecodeString(encodedTx)
  2333  		if err != nil {
  2334  			return err
  2335  		}
  2336  		stxStr := base64.StdEncoding.EncodeToString(sigTxs[i])
  2337  		if !bytes.Equal(gold, sigTxs[i]) {
  2338  			return fmt.Errorf("Application signed transaction does not match the golden: %s != %s", stxStr, encodedTx)
  2339  		}
  2340  	}
  2341  
  2342  	return nil
  2343  }
  2344  
  2345  func iBuildAPaymentTransactionWithSenderReceiverAmountCloseRemainderTo(sender, receiver string, amount int, closeTo string) error {
  2346  	if amount < 0 {
  2347  		return fmt.Errorf("amount must be a positive integer")
  2348  	}
  2349  
  2350  	if sender == "transient" {
  2351  		sender = transientAccount.Address.String()
  2352  	}
  2353  
  2354  	if receiver == "transient" {
  2355  		receiver = transientAccount.Address.String()
  2356  	}
  2357  
  2358  	var err error
  2359  	txn, err = future.MakePaymentTxn(sender, receiver, uint64(amount), nil, closeTo, sugParams)
  2360  	tx = txn
  2361  	return err
  2362  }
  2363  
  2364  func iCreateATransactionWithSignerWithTheCurrentTransaction() error {
  2365  	accountTxAndSigner = future.TransactionWithSigner{
  2366  		Signer: accountTxSigner,
  2367  		Txn:    txn,
  2368  	}
  2369  	return nil
  2370  }
  2371  
  2372  func iAppendTheCurrentTransactionWithSignerToTheMethodArgumentsArray() error {
  2373  	methodArgs = append(methodArgs, accountTxAndSigner)
  2374  	return nil
  2375  }
  2376  
  2377  func theDecodedTransactionShouldEqualTheOriginal() error {
  2378  	var decodedTx types.SignedTxn
  2379  	err := msgpack.Decode(stx, &decodedTx)
  2380  	if err != nil {
  2381  		return err
  2382  	}
  2383  
  2384  	// This test isn't perfect as it's sensitive to non-meaningful changes (e.g. nil slice vs 0
  2385  	// length slice), but it's good enough for now. We may want a Transaction.Equals method in the
  2386  	// future.
  2387  	if !reflect.DeepEqual(tx, decodedTx.Txn) {
  2388  		return fmt.Errorf("Transactions unequal: %#v != %#v", tx, decodedTx.Txn)
  2389  	}
  2390  
  2391  	return nil
  2392  }
  2393  
  2394  func aDryrunResponseFileAndATransactionAtIndex(arg1, arg2 string) error {
  2395  	data, err := loadResource(arg1)
  2396  	if err != nil {
  2397  		return err
  2398  	}
  2399  	dr, err := future.NewDryrunResponseFromJson(data)
  2400  	if err != nil {
  2401  		return err
  2402  	}
  2403  	idx, err := strconv.Atoi(arg2)
  2404  	if err != nil {
  2405  		return err
  2406  	}
  2407  	txTrace = dr.Txns[idx]
  2408  	return nil
  2409  }
  2410  
  2411  func callingAppTraceProduces(arg1 string) error {
  2412  	cfg := future.DefaultStackPrinterConfig()
  2413  	cfg.TopOfStackFirst = false
  2414  	trace = txTrace.GetAppCallTrace(cfg)
  2415  
  2416  	data, err := loadResource(arg1)
  2417  	if err != nil {
  2418  		return err
  2419  	}
  2420  	if string(data) != trace {
  2421  		return fmt.Errorf("No matching trace: \n'%s'\nvs\n'%s'\n", string(data), trace)
  2422  	}
  2423  	return nil
  2424  }
  2425  
  2426  func aSourceMapJsonFile(srcMapJsonPath string) error {
  2427  	b, err := loadResource(srcMapJsonPath)
  2428  	if err != nil {
  2429  		return err
  2430  	}
  2431  
  2432  	ism := map[string]interface{}{}
  2433  	if err := json.Unmarshal(b, &ism); err != nil {
  2434  		return err
  2435  	}
  2436  
  2437  	sourceMap, err = logic.DecodeSourceMap(ism)
  2438  
  2439  	return err
  2440  }
  2441  
  2442  func theStringComposedOfPclineNumberEquals(expectedPcToLineString string) error {
  2443  	var buff []string
  2444  	for pc := 0; pc < len(sourceMap.PcToLine); pc++ {
  2445  		line := sourceMap.PcToLine[pc]
  2446  		buff = append(buff, fmt.Sprintf("%d:%d", pc, line))
  2447  	}
  2448  	actualStr := strings.Join(buff, ";")
  2449  	if expectedPcToLineString != actualStr {
  2450  		return fmt.Errorf("Expected %s got %s", expectedPcToLineString, actualStr)
  2451  	}
  2452  	return nil
  2453  }
  2454  
  2455  func gettingTheLineAssociatedWithAPcEquals(strPc, strLine string) error {
  2456  	pc, _ := strconv.Atoi(strPc)
  2457  	expectedLine, _ := strconv.Atoi(strLine)
  2458  
  2459  	actualLine, ok := sourceMap.GetLineForPc(pc)
  2460  	if !ok {
  2461  		return fmt.Errorf("expected valid line, got !ok")
  2462  	}
  2463  
  2464  	if actualLine != expectedLine {
  2465  		return fmt.Errorf("expected %d got %d", expectedLine, actualLine)
  2466  	}
  2467  
  2468  	return nil
  2469  }
  2470  
  2471  func gettingTheLastPcAssociatedWithALineEquals(strLine, strPc string) error {
  2472  	expectedPc, _ := strconv.Atoi(strPc)
  2473  	line, _ := strconv.Atoi(strLine)
  2474  
  2475  	pcs := sourceMap.GetPcsForLine(line)
  2476  	actualPc := pcs[len(pcs)-1]
  2477  
  2478  	if actualPc != expectedPc {
  2479  		return fmt.Errorf("expected %d got %d", expectedPc, actualPc)
  2480  	}
  2481  
  2482  	return nil
  2483  }
  2484  
  2485  func iCompileATealProgramWithMappingEnabled(programPath string) error {
  2486  	fileContents, err := loadResource(programPath)
  2487  	if err != nil {
  2488  		return err
  2489  	}
  2490  
  2491  	result, err := aclv2.TealCompile(fileContents).Sourcemap(true).Do(context.Background())
  2492  	if err != nil {
  2493  		return err
  2494  	}
  2495  
  2496  	if result.Sourcemap == nil {
  2497  		return fmt.Errorf("No source map returned")
  2498  	}
  2499  
  2500  	srcMapping = *result.Sourcemap
  2501  	return nil
  2502  }
  2503  
  2504  func theResultingSourceMapIsTheSameAsTheJson(expectedJsonPath string) error {
  2505  
  2506  	expectedJson, err := loadResource(expectedJsonPath)
  2507  	if err != nil {
  2508  		return err
  2509  	}
  2510  
  2511  	// Marshal the map to json then unmarshal it so we get alphabetic ordering
  2512  	expectedMap := map[string]interface{}{}
  2513  	err = json.Unmarshal(expectedJson, &expectedMap)
  2514  	if err != nil {
  2515  		return err
  2516  	}
  2517  
  2518  	expectedJson, err = json.Marshal(expectedMap)
  2519  	if err != nil {
  2520  		return err
  2521  	}
  2522  
  2523  	// Turn it back into a string
  2524  	actualJson, err := json.Marshal(srcMapping)
  2525  	if err != nil {
  2526  		return nil
  2527  	}
  2528  
  2529  	if !bytes.Equal(expectedJson, actualJson) {
  2530  		return fmt.Errorf("expected %s got %s", expectedJson, actualJson)
  2531  	}
  2532  
  2533  	return nil
  2534  }
  2535  
  2536  func takeB64encodedBytes(b64encodedBytes string) error {
  2537  	var err error
  2538  	seeminglyProgram, err = base64.StdEncoding.DecodeString(b64encodedBytes)
  2539  	if err != nil {
  2540  		return err
  2541  	}
  2542  	return nil
  2543  }
  2544  
  2545  func heuristicCheckOverBytes() error {
  2546  	_, sanityCheckError = crypto.MakeLogicSigAccountEscrowChecked(seeminglyProgram, nil)
  2547  	return nil
  2548  }
  2549  
  2550  func checkErrorIfMatching(errMsg string) error {
  2551  	if len(errMsg) == 0 {
  2552  		if sanityCheckError != nil {
  2553  			return fmt.Errorf("expected err message to be empty, but sanity check says %w", sanityCheckError)
  2554  		}
  2555  	} else {
  2556  		if sanityCheckError == nil || !strings.Contains(sanityCheckError.Error(), errMsg) {
  2557  			return fmt.Errorf("expected err to contain %s, but sanity check error not matching: %w", errMsg, sanityCheckError)
  2558  		}
  2559  	}
  2560  	return nil
  2561  }