func MakeApplicationUpdateTx(
	appIdx uint64,
	appArgs [][]byte,
	accounts []string,
	foreignApps []uint64,
	foreignAssets []uint64,
	approvalProg []byte,
	clearProg []byte,
	sp types.SuggestedParams,
	sender types.Address,
	note []byte,
	group types.Digest,
	lease [32]byte,
	rekeyTo types.Address) (tx types.Transaction, err error) {
	return MakeApplicationCallTx(appIdx,
		appArgs,
		accounts,
		foreignApps,
		foreignAssets,
		types.UpdateApplicationOC,
		approvalProg,
		clearProg,
		emptySchema,
		emptySchema,
		sp,
		sender,
		note,
		group,
		lease,
		rekeyTo,
	)
}
MakeApplicationUpdateTx makes a transaction for updating an application's programs (see above for args desc.)
package future
import (
	"encoding/base64"
	"fmt"
	"github.com/algorand/go-algorand-sdk/transaction"
	"github.com/algorand/go-algorand-sdk/types"
)
const MinTxnFee = transaction.MinTxnFee
func setFee(tx types.Transaction, params types.SuggestedParams) (types.Transaction, error) {
	if !params.FlatFee {
		eSize, err := transaction.EstimateSize(tx)
		if err != nil {
			return types.Transaction{}, err
		}
		tx.Fee = types.MicroAlgos(eSize * uint64(params.Fee))
		if tx.Fee < MinTxnFee {
			tx.Fee = MinTxnFee
		}
	} else {
		tx.Fee = params.Fee
	}
	return tx, nil
}
func MakePaymentTxn(from, to string, amount uint64, note []byte, closeRemainderTo string, params types.SuggestedParams) (types.Transaction, error) {
	fromAddr, err := types.DecodeAddress(from)
	if err != nil {
		return types.Transaction{}, err
	}
	toAddr, err := types.DecodeAddress(to)
	if err != nil {
		return types.Transaction{}, err
	}
	var closeRemainderToAddr types.Address
	if closeRemainderTo != "" {
		closeRemainderToAddr, err = types.DecodeAddress(closeRemainderTo)
		if err != nil {
			return types.Transaction{}, err
		}
	}
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("payment transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	tx := types.Transaction{
		Type: types.PaymentTx,
		Header: types.Header{
			Sender:      fromAddr,
			Fee:         params.Fee,
			FirstValid:  params.FirstRoundValid,
			LastValid:   params.LastRoundValid,
			Note:        note,
			GenesisID:   params.GenesisID,
			GenesisHash: gh,
		},
		PaymentTxnFields: types.PaymentTxnFields{
			Receiver:         toAddr,
			Amount:           types.MicroAlgos(amount),
			CloseRemainderTo: closeRemainderToAddr,
		},
	}
	return setFee(tx, params)
}
func MakeKeyRegTxn(account string, note []byte, params types.SuggestedParams, voteKey, selectionKey string, voteFirst, voteLast, voteKeyDilution uint64) (types.Transaction, error) {
	accountAddr, err := types.DecodeAddress(account)
	if err != nil {
		return types.Transaction{}, err
	}
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("key registration transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	votePKBytes, err := byte32FromBase64(voteKey)
	if err != nil {
		return types.Transaction{}, err
	}
	selectionPKBytes, err := byte32FromBase64(selectionKey)
	if err != nil {
		return types.Transaction{}, err
	}
	tx := types.Transaction{
		Type: types.KeyRegistrationTx,
		Header: types.Header{
			Sender:      accountAddr,
			Fee:         params.Fee,
			FirstValid:  params.FirstRoundValid,
			LastValid:   params.LastRoundValid,
			Note:        note,
			GenesisHash: gh,
			GenesisID:   params.GenesisID,
		},
		KeyregTxnFields: types.KeyregTxnFields{
			VotePK:          types.VotePK(votePKBytes),
			SelectionPK:     types.VRFPK(selectionPKBytes),
			VoteFirst:       types.Round(voteFirst),
			VoteLast:        types.Round(voteLast),
			VoteKeyDilution: voteKeyDilution,
		},
	}
	return setFee(tx, params)
}
func MakeAssetCreateTxn(account string, note []byte, params types.SuggestedParams, total uint64, decimals uint32, defaultFrozen bool, manager, reserve, freeze, clawback string, unitName, assetName, url, metadataHash string) (types.Transaction, error) {
	var tx types.Transaction
	var err error
	if decimals > types.AssetMaxNumberOfDecimals {
		return tx, fmt.Errorf("cannot create an asset with number of decimals %d (more than maximum %d)", decimals, types.AssetMaxNumberOfDecimals)
	}
	tx.Type = types.AssetConfigTx
	tx.AssetParams = types.AssetParams{
		Total:         total,
		Decimals:      decimals,
		DefaultFrozen: defaultFrozen,
		UnitName:      unitName,
		AssetName:     assetName,
		URL:           url,
	}
	if manager != "" {
		tx.AssetParams.Manager, err = types.DecodeAddress(manager)
		if err != nil {
			return tx, err
		}
	}
	if reserve != "" {
		tx.AssetParams.Reserve, err = types.DecodeAddress(reserve)
		if err != nil {
			return tx, err
		}
	}
	if freeze != "" {
		tx.AssetParams.Freeze, err = types.DecodeAddress(freeze)
		if err != nil {
			return tx, err
		}
	}
	if clawback != "" {
		tx.AssetParams.Clawback, err = types.DecodeAddress(clawback)
		if err != nil {
			return tx, err
		}
	}
	if len(assetName) > types.AssetNameMaxLen {
		return tx, fmt.Errorf("asset name too long: %d > %d", len(assetName), types.AssetNameMaxLen)
	}
	tx.AssetParams.AssetName = assetName
	if len(url) > types.AssetURLMaxLen {
		return tx, fmt.Errorf("asset url too long: %d > %d", len(url), types.AssetURLMaxLen)
	}
	tx.AssetParams.URL = url
	if len(unitName) > types.AssetUnitNameMaxLen {
		return tx, fmt.Errorf("asset unit name too long: %d > %d", len(unitName), types.AssetUnitNameMaxLen)
	}
	tx.AssetParams.UnitName = unitName
	if len(metadataHash) > types.AssetMetadataHashLen {
		return tx, fmt.Errorf("asset metadata hash '%s' too long: %d > %d)", metadataHash, len(metadataHash), types.AssetMetadataHashLen)
	}
	copy(tx.AssetParams.MetadataHash[:], []byte(metadataHash))
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	accountAddr, err := types.DecodeAddress(account)
	if err != nil {
		return types.Transaction{}, err
	}
	tx.Header = types.Header{
		Sender:      accountAddr,
		Fee:         params.Fee,
		FirstValid:  params.FirstRoundValid,
		LastValid:   params.LastRoundValid,
		GenesisHash: gh,
		GenesisID:   params.GenesisID,
		Note:        note,
	}
	return setFee(tx, params)
}
func MakeAssetConfigTxn(account string, note []byte, params types.SuggestedParams, index uint64, newManager, newReserve, newFreeze, newClawback string, strictEmptyAddressChecking bool) (types.Transaction, error) {
	var tx types.Transaction
	if strictEmptyAddressChecking && (newManager == "" || newReserve == "" || newFreeze == "" || newClawback == "") {
		return tx, fmt.Errorf("strict empty address checking requested but empty address supplied to one or more manager addresses")
	}
	tx.Type = types.AssetConfigTx
	accountAddr, err := types.DecodeAddress(account)
	if err != nil {
		return tx, err
	}
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	tx.Header = types.Header{
		Sender:      accountAddr,
		Fee:         params.Fee,
		FirstValid:  params.FirstRoundValid,
		LastValid:   params.LastRoundValid,
		GenesisHash: gh,
		GenesisID:   params.GenesisID,
		Note:        note,
	}
	tx.ConfigAsset = types.AssetIndex(index)
	if newManager != "" {
		tx.Type = types.AssetConfigTx
		tx.AssetParams.Manager, err = types.DecodeAddress(newManager)
		if err != nil {
			return tx, err
		}
	}
	if newReserve != "" {
		tx.AssetParams.Reserve, err = types.DecodeAddress(newReserve)
		if err != nil {
			return tx, err
		}
	}
	if newFreeze != "" {
		tx.AssetParams.Freeze, err = types.DecodeAddress(newFreeze)
		if err != nil {
			return tx, err
		}
	}
	if newClawback != "" {
		tx.AssetParams.Clawback, err = types.DecodeAddress(newClawback)
		if err != nil {
			return tx, err
		}
	}
	return setFee(tx, params)
}
func transferAssetBuilder(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, index uint64, closeAssetsTo, revocationTarget string) (types.Transaction, error) {
	var tx types.Transaction
	tx.Type = types.AssetTransferTx
	accountAddr, err := types.DecodeAddress(account)
	if err != nil {
		return tx, err
	}
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	tx.Header = types.Header{
		Sender:      accountAddr,
		Fee:         params.Fee,
		FirstValid:  params.FirstRoundValid,
		LastValid:   params.LastRoundValid,
		GenesisHash: gh,
		GenesisID:   params.GenesisID,
		Note:        note,
	}
	tx.XferAsset = types.AssetIndex(index)
	recipientAddr, err := types.DecodeAddress(recipient)
	if err != nil {
		return tx, err
	}
	tx.AssetReceiver = recipientAddr
	if closeAssetsTo != "" {
		closeToAddr, err := types.DecodeAddress(closeAssetsTo)
		if err != nil {
			return tx, err
		}
		tx.AssetCloseTo = closeToAddr
	}
	if revocationTarget != "" {
		revokedAddr, err := types.DecodeAddress(revocationTarget)
		if err != nil {
			return tx, err
		}
		tx.AssetSender = revokedAddr
	}
	tx.AssetAmount = amount
	return setFee(tx, params)
}
func MakeAssetTransferTxn(account, recipient string, amount uint64, note []byte, params types.SuggestedParams, closeAssetsTo string, index uint64) (types.Transaction, error) {
	revocationTarget := ""  
	return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, revocationTarget)
}
func MakeAssetAcceptanceTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) {
	return MakeAssetTransferTxn(account, account, 0, note, params, "", index)
}
func MakeAssetRevocationTxn(account, target string, amount uint64, recipient string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) {
	closeAssetsTo := ""  
	return transferAssetBuilder(account, recipient, amount, note, params, index, closeAssetsTo, target)
}
func MakeAssetDestroyTxn(account string, note []byte, params types.SuggestedParams, index uint64) (types.Transaction, error) {
	return MakeAssetConfigTxn(account, note, params, index, "", "", "", "", false)
}
func MakeAssetFreezeTxn(account string, note []byte, params types.SuggestedParams, assetIndex uint64, target string, newFreezeSetting bool) (types.Transaction, error) {
	var tx types.Transaction
	tx.Type = types.AssetFreezeTx
	accountAddr, err := types.DecodeAddress(account)
	if err != nil {
		return tx, err
	}
	if len(params.GenesisHash) == 0 {
		return types.Transaction{}, fmt.Errorf("asset transaction must contain a genesisHash")
	}
	var gh types.Digest
	copy(gh[:], params.GenesisHash)
	tx.Header = types.Header{
		Sender:      accountAddr,
		Fee:         params.Fee,
		FirstValid:  params.FirstRoundValid,
		LastValid:   params.LastRoundValid,
		GenesisHash: gh,
		GenesisID:   params.GenesisID,
		Note:        note,
	}
	tx.FreezeAsset = types.AssetIndex(assetIndex)
	tx.FreezeAccount, err = types.DecodeAddress(target)
	if err != nil {
		return tx, err
	}
	tx.AssetFrozen = newFreezeSetting
	return setFee(tx, params)
}
func byte32FromBase64(in string) (out [32]byte, err error) {
	slice, err := base64.StdEncoding.DecodeString(in)
	if err != nil {
		return
	}
	if len(slice) != 32 {
		return out, fmt.Errorf("Input is not 32 bytes")
	}
	copy(out[:], slice)
	return
}
func MakeApplicationCreateTx(
	optIn bool,
	approvalProg []byte,
	clearProg []byte,
	globalSchema types.StateSchema,
	localSchema types.StateSchema,
	appArgs [][]byte,
	accounts []string,
	foreignApps []uint64,
	foreignAssets []uint64,
	sp types.SuggestedParams,
	sender types.Address,
	note []byte,
	group types.Digest,
	lease [32]byte,
	rekeyTo types.Address) (tx types.Transaction, err error) {
	oncomp := types.NoOpOC
	if optIn {
		oncomp = types.OptInOC
	}
	return MakeApplicationCallTx(
		0,
		appArgs,
		accounts,
		foreignApps,
		foreignAssets,
		oncomp,
		approvalProg,
		clearProg,
		globalSchema,
		localSchema,
		sp,
		sender,
		note,
		group,
		lease,
		rekeyTo,
	)
}
func MakeApplicationCreateTxWithExtraPages(
	optIn bool,
	approvalProg []byte,
	clearProg []byte,
	globalSchema types.StateSchema,
	localSchema types.StateSchema,
	appArgs [][]byte,
	accounts []string,
	foreignApps []uint64,
	foreignAssets []uint64,
	sp types.SuggestedParams,
	sender types.Address,
	note []byte,
	group types.Digest,
	lease [32]byte,
	rekeyTo types.Address, extraPages uint32) (tx types.Transaction, err error) {
	oncomp := types.NoOpOC
	if optIn {
		oncomp = types.OptInOC
	}
	appCallTx, err := MakeApplicationCallTx(
		0,
		appArgs,
		accounts,
		foreignApps,
		foreignAssets,
		oncomp,
		approvalProg,
		clearProg,
		globalSchema,
		localSchema,
		sp,
		sender,
		note,
		group,
		lease,
		rekeyTo)
	if err != nil {
		return
	}
	return MakeApplicationCallTxWithExtraPages(appCallTx, extraPages)
}