Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions cmd/goal/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var (

extraPages uint32

createOnCompletion string
onCompletion string

localSchemaUints uint64
localSchemaByteSlices uint64
Expand Down Expand Up @@ -106,7 +106,7 @@ func init() {
createAppCmd.Flags().Uint64Var(&localSchemaUints, "local-ints", 0, "Maximum number of integer values that may be stored in local (per-account) key/value stores for this app. Immutable.")
createAppCmd.Flags().Uint64Var(&localSchemaByteSlices, "local-byteslices", 0, "Maximum number of byte slices that may be stored in local (per-account) key/value stores for this app. Immutable.")
createAppCmd.Flags().StringVar(&appCreator, "creator", "", "Account to create the application")
createAppCmd.Flags().StringVar(&createOnCompletion, "on-completion", "NoOp", "OnCompletion action for application transaction")
createAppCmd.Flags().StringVar(&onCompletion, "on-completion", "NoOp", "OnCompletion action for application transaction")
createAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger TEAL assembly program. A maximum of 3 extra pages is allowed. A page is 1024 bytes.")

callAppCmd.Flags().StringVarP(&account, "from", "f", "", "Account to call app from")
Expand All @@ -120,6 +120,7 @@ func init() {

methodAppCmd.Flags().StringVar(&method, "method", "", "Method to be called")
methodAppCmd.Flags().StringArrayVar(&methodArgs, "arg", nil, "Args to pass in for calling a method")
methodAppCmd.Flags().StringVar(&onCompletion, "on-completion", "NoOp", "OnCompletion action for application transaction")

// Can't use PersistentFlags on the root because for some reason marking
// a root command as required with MarkPersistentFlagRequired isn't
Expand Down Expand Up @@ -432,15 +433,15 @@ var createAppCmd = &cobra.Command{

// Parse transaction parameters
approvalProg, clearProg := mustParseProgArgs()
onCompletion := mustParseOnCompletion(createOnCompletion)
onCompletionEnum := mustParseOnCompletion(onCompletion)
appArgs, appAccounts, foreignApps, foreignAssets := getAppInputs()

switch onCompletion {
switch onCompletionEnum {
case transactions.CloseOutOC, transactions.ClearStateOC:
reportWarnf("'--on-completion %s' may be ill-formed for 'goal app create'", createOnCompletion)
reportWarnf("'--on-completion %s' may be ill-formed for 'goal app create'", onCompletion)
}

tx, err := client.MakeUnsignedAppCreateTx(onCompletion, approvalProg, clearProg, globalSchema, localSchema, appArgs, appAccounts, foreignApps, foreignAssets, extraPages)
tx, err := client.MakeUnsignedAppCreateTx(onCompletionEnum, approvalProg, clearProg, globalSchema, localSchema, appArgs, appAccounts, foreignApps, foreignAssets, extraPages)
if err != nil {
reportErrorf("Cannot create application txn: %v", err)
}
Expand Down Expand Up @@ -1060,14 +1061,14 @@ var methodAppCmd = &cobra.Command{
reportErrorf("in goal app method: --arg and --app-arg are mutually exclusive, do not use --app-arg")
}

onCompletion := mustParseOnCompletion(createOnCompletion)
onCompletionEnum := mustParseOnCompletion(onCompletion)

if appIdx == 0 {
reportErrorf("app id == 0, goal app create not supported in goal app method")
}

var approvalProg, clearProg []byte
if onCompletion == transactions.UpdateApplicationOC {
if onCompletionEnum == transactions.UpdateApplicationOC {
approvalProg, clearProg = mustParseProgArgs()
}

Expand All @@ -1089,7 +1090,7 @@ var methodAppCmd = &cobra.Command{

tx, err := client.MakeUnsignedApplicationCallTx(
appIdx, applicationArgs, appAccounts, foreignApps, foreignAssets,
onCompletion, approvalProg, clearProg, basics.StateSchema{}, basics.StateSchema{}, 0)
onCompletionEnum, approvalProg, clearProg, basics.StateSchema{}, basics.StateSchema{}, 0)

if err != nil {
reportErrorf("Cannot create application txn: %v", err)
Expand Down Expand Up @@ -1155,6 +1156,7 @@ var methodAppCmd = &cobra.Command{
}

if retTypeStr == "void" {
fmt.Printf("method %s succeeded", method)
return
}

Expand Down Expand Up @@ -1192,7 +1194,7 @@ var methodAppCmd = &cobra.Command{
if err != nil {
reportErrorf("cannot marshal returned bytes %v to JSON: %v", decoded, err)
}
fmt.Printf("method %s output: %s\n", method, string(decodedJSON))
fmt.Printf("method %s succeeded with output: %s", method, string(decodedJSON))
}
},
}
44 changes: 33 additions & 11 deletions test/scripts/e2e_subs/e2e-app-abi-add.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,48 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

gcmd="goal -w ${WALLET}"

GLOBAL_INTS=2
ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')

printf '#pragma version 2\nint 1' > "${TEMPDIR}/simple.teal"
PROGRAM=($(${gcmd} clerk compile "${TEMPDIR}/simple.teal"))
APPID=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog ${DIR}/tealprogs/app-abi-add-example.teal --clear-prog ${TEMPDIR}/simple.teal --global-byteslices 0 --global-ints ${GLOBAL_INTS} --local-byteslices 0 --local-ints 0 | grep Created | awk '{ print $6 }')
APPID=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog ${DIR}/tealprogs/app-abi-add-example.teal --clear-prog ${TEMPDIR}/simple.teal --global-byteslices 0 --global-ints 0 --local-byteslices 1 --local-ints 0 | grep Created | awk '{ print $6 }')

# Should succeed to opt in
${gcmd} app optin --app-id $APPID --from $ACCOUNT
# Opt in
RES=$(${gcmd} app method --method "optIn(string)string" --arg "\"Algorand Fan\"" --on-completion optin --app-id $APPID --from $ACCOUNT 2>&1 || true)
EXPECTED="method optIn(string)string succeeded with output: \"hello Algorand Fan\""
if [[ $RES != *"${EXPECTED}"* ]]; then
date '+app-abi-add-test FAIL the method call to optIn(string)string should not fail %Y%m%d_%H%M%S'
false
fi

# Call should now succeed
# 1 + 2 = 3
RES=$(${gcmd} app method --method "add(uint64,uint64)uint64" --arg 1 --arg 2 --app-id $APPID --from $ACCOUNT 2>&1 || true)
EXPECTED="method add(uint64,uint64)uint64 output: 3"
EXPECTED="method add(uint64,uint64)uint64 succeeded with output: 3"
if [[ $RES != *"${EXPECTED}"* ]]; then
date '+app-abi-add-test FAIL the application creation should not fail %Y%m%d_%H%M%S'
date '+app-abi-add-test FAIL the method call to add(uint64,uint64)uint64 should not fail %Y%m%d_%H%M%S'
false
fi

# Delete application should still succeed
${gcmd} app delete --app-id $APPID --from $ACCOUNT
# 18446744073709551614 + 1 = 18446744073709551615
RES=$(${gcmd} app method --method "add(uint64,uint64)uint64" --arg 18446744073709551614 --arg 1 --app-id $APPID --from $ACCOUNT 2>&1 || true)
EXPECTED="method add(uint64,uint64)uint64 succeeded with output: 18446744073709551615"
if [[ $RES != *"${EXPECTED}"* ]]; then
date '+app-abi-add-test FAIL the method call to add(uint64,uint64)uint64 should not fail %Y%m%d_%H%M%S'
false
fi

# Clear should still succeed
${gcmd} app clear --app-id $APPID --from $ACCOUNT
# Close out
RES=$(${gcmd} app method --method "closeOut()string" --on-completion closeout --app-id $APPID --from $ACCOUNT 2>&1 || true)
EXPECTED="method closeOut()string succeeded with output: \"goodbye Algorand Fan\""
if [[ $RES != *"${EXPECTED}"* ]]; then
date '+app-abi-add-test FAIL the method call to closeOut()string should not fail %Y%m%d_%H%M%S'
false
fi

# Delete
RES=$(${gcmd} app method --method "delete()void" --on-completion deleteapplication --app-id $APPID --from $ACCOUNT 2>&1 || true)
EXPECTED="method delete()void succeeded"
if [[ $RES != *"${EXPECTED}"* ]]; then
date '+app-abi-add-test FAIL the method call to delete()void should not fail %Y%m%d_%H%M%S'
false
fi
159 changes: 118 additions & 41 deletions test/scripts/e2e_subs/tealprogs/app-abi-add-example.teal
Original file line number Diff line number Diff line change
@@ -1,87 +1,164 @@
// generated from https://gist.github.com/jasonpaulos/99e4f8a75f2fc2ec9b8073c064530359
#pragma version 5
intcblock 1 0
bytecblock 0x151f7c75
txn ApplicationID
intc_1 // 0
int 0
==
bnz main_l12
bnz main_l14
txn OnCompletion
intc_0 // OptIn
int OptIn
==
bnz main_l11
txna ApplicationArgs 0
byte 0xcfa68e36
==
&&
bnz main_l13
txn OnCompletion
pushint 5 // DeleteApplication
int CloseOut
==
bnz main_l10
txna ApplicationArgs 0
byte 0xa9f42b3d
==
&&
bnz main_l12
txn OnCompletion
intc_1 // NoOp
int DeleteApplication
==
txna ApplicationArgs 0
pushbytes 0xfe6bdf69 // 0xfe6bdf69
byte 0x24378d3c
==
&&
bnz main_l9
bnz main_l11
txn OnCompletion
intc_1 // NoOp
int NoOp
==
txna ApplicationArgs 0
pushbytes 0xa88c26a5 // 0xa88c26a5
byte 0xfe6bdf69
==
&&
bnz main_l8
bnz main_l10
txn OnCompletion
intc_1 // NoOp
int NoOp
==
txna ApplicationArgs 0
pushbytes 0x535a47ba // 0x535a47ba
byte 0xa88c26a5
==
&&
bnz main_l7
intc_1 // 0
return
main_l7:
txna ApplicationArgs 1
callsub sub2
intc_0 // 1
bnz main_l9
txn OnCompletion
int NoOp
==
txna ApplicationArgs 0
byte 0x535a47ba
==
&&
bnz main_l8
int 0
return
main_l8:
callsub sub1
intc_0 // 1
txna ApplicationArgs 1
callsub sub5
int 1
return
main_l9:
txna ApplicationArgs 1
txna ApplicationArgs 2
callsub sub0
intc_0 // 1
callsub sub4
int 1
return
main_l10:
intc_0 // 1
txna ApplicationArgs 1
txna ApplicationArgs 2
callsub sub3
int 1
return
main_l11:
intc_0 // 1
callsub sub2
int 1
return
main_l12:
intc_0 // 1
callsub sub1
int 1
return
sub0: // add
store 1
main_l13:
txna ApplicationArgs 1
callsub sub0
int 1
return
main_l14:
int 1
return
sub0: // optIn
store 0
bytec_0 // 0x151f7c75
int 0
byte "name"
load 0
btoi
extract 2 0
app_local_put
byte "hello "
int 0
byte "name"
app_local_get
concat
store 1
byte 0x151f7c75
load 1
len
itob
extract 6 2
concat
load 1
concat
log
retsub
sub1: // closeOut
byte "goodbye "
int 0
byte "name"
app_local_get
concat
store 2
byte 0x151f7c75
load 2
len
itob
extract 6 2
concat
load 2
concat
log
retsub
sub2: // deleteApp
txn Sender
global CreatorAddress
==
assert
retsub
sub3: // add
store 4
store 3
byte 0x151f7c75
load 3
btoi
load 4
btoi
+
itob
concat
log
retsub
sub1: // empty
bytec_0 // 0x151f7c75
sub4: // empty
byte "random inconsequential log"
log
retsub
sub2: // payment
store 2
pushbytes 0x151f7c7580 // 0x151f7c7580
sub5: // payment
store 5
txn GroupIndex
int 1
-
gtxns TypeEnum
int pay
==
assert
byte 0x151f7c75
byte 0x80
concat
log
retsub