@@ -1074,7 +1074,7 @@ func populateMethodCallTxnArgs(types []string, values []string) ([]transactions.
10741074 }
10751075
10761076 expectedType := types [i ]
1077- if expectedType != "txn" && txn .Txn .Type != protocol .TxType (expectedType ) {
1077+ if expectedType != abi . AnyTransactionType && txn .Txn .Type != protocol .TxType (expectedType ) {
10781078 return nil , fmt .Errorf ("Transaction from %s does not match method argument type. Expected %s, got %s" , txFilename , expectedType , txn .Txn .Type )
10791079 }
10801080
@@ -1084,6 +1084,82 @@ func populateMethodCallTxnArgs(types []string, values []string) ([]transactions.
10841084 return loadedTxns , nil
10851085}
10861086
1087+ // populateMethodCallReferenceArgs parses reference argument types and resolves them to an index
1088+ // into the appropriate foreign array. Their placement will be as compact as possible, which means
1089+ // values will be deduplicated and any value that is the sender or the current app will not be added
1090+ // to the foreign array.
1091+ func populateMethodCallReferenceArgs (sender string , currentApp uint64 , types []string , values []string , accounts * []string , apps * []uint64 , assets * []uint64 ) ([]int , error ) {
1092+ resolvedIndexes := make ([]int , len (types ))
1093+
1094+ for i , value := range values {
1095+ var resolved int
1096+
1097+ switch types [i ] {
1098+ case abi .AccountReferenceType :
1099+ if value == sender {
1100+ resolved = 0
1101+ } else {
1102+ duplicate := false
1103+ for j , account := range * accounts {
1104+ if value == account {
1105+ resolved = j + 1 // + 1 because 0 is the sender
1106+ duplicate = true
1107+ break
1108+ }
1109+ }
1110+ if ! duplicate {
1111+ resolved = len (* accounts ) + 1
1112+ * accounts = append (* accounts , value )
1113+ }
1114+ }
1115+ case abi .ApplicationReferenceType :
1116+ appID , err := strconv .ParseUint (value , 10 , 64 )
1117+ if err != nil {
1118+ return nil , fmt .Errorf ("Unable to parse application ID '%s': %s" , value , err )
1119+ }
1120+ if appID == currentApp {
1121+ resolved = 0
1122+ } else {
1123+ duplicate := false
1124+ for j , app := range * apps {
1125+ if appID == app {
1126+ resolved = j + 1 // + 1 because 0 is the current app
1127+ duplicate = true
1128+ break
1129+ }
1130+ }
1131+ if ! duplicate {
1132+ resolved = len (* apps ) + 1
1133+ * apps = append (* apps , appID )
1134+ }
1135+ }
1136+ case abi .AssetReferenceType :
1137+ assetID , err := strconv .ParseUint (value , 10 , 64 )
1138+ if err != nil {
1139+ return nil , fmt .Errorf ("Unable to parse asset ID '%s': %s" , value , err )
1140+ }
1141+ duplicate := false
1142+ for j , asset := range * assets {
1143+ if assetID == asset {
1144+ resolved = j
1145+ duplicate = true
1146+ break
1147+ }
1148+ }
1149+ if ! duplicate {
1150+ resolved = len (* assets )
1151+ * assets = append (* assets , assetID )
1152+ }
1153+ default :
1154+ return nil , fmt .Errorf ("Unknown reference type: %s" , types [i ])
1155+ }
1156+
1157+ resolvedIndexes [i ] = resolved
1158+ }
1159+
1160+ return resolvedIndexes , nil
1161+ }
1162+
10871163var methodAppCmd = & cobra.Command {
10881164 Use : "method" ,
10891165 Short : "Invoke a method" ,
@@ -1138,17 +1214,37 @@ var methodAppCmd = &cobra.Command{
11381214 var txnArgValues []string
11391215 var basicArgTypes []string
11401216 var basicArgValues []string
1217+ var refArgTypes []string
1218+ var refArgValues []string
1219+ refArgIndexToBasicArgIndex := make (map [int ]int )
11411220 for i , argType := range argTypes {
11421221 argValue := methodArgs [i ]
11431222 if abi .IsTransactionType (argType ) {
11441223 txnArgTypes = append (txnArgTypes , argType )
11451224 txnArgValues = append (txnArgValues , argValue )
11461225 } else {
1226+ if abi .IsReferenceType (argType ) {
1227+ refArgIndexToBasicArgIndex [len (refArgTypes )] = len (basicArgTypes )
1228+ refArgTypes = append (refArgTypes , argType )
1229+ refArgValues = append (refArgValues , argValue )
1230+ // treat the reference as a uint8 for encoding purposes
1231+ argType = "uint8"
1232+ }
11471233 basicArgTypes = append (basicArgTypes , argType )
11481234 basicArgValues = append (basicArgValues , argValue )
11491235 }
11501236 }
11511237
1238+ refArgsResolved , err := populateMethodCallReferenceArgs (account , appIdx , refArgTypes , refArgValues , & appAccounts , & foreignApps , & foreignAssets )
1239+ if err != nil {
1240+ reportErrorf ("error populating reference arguments: %v" , err )
1241+ }
1242+ for i , resolved := range refArgsResolved {
1243+ basicArgIndex := refArgIndexToBasicArgIndex [i ]
1244+ // use the foreign array index as the encoded argument value
1245+ basicArgValues [basicArgIndex ] = strconv .Itoa (resolved )
1246+ }
1247+
11521248 err = abi .ParseArgJSONtoByteSlice (basicArgTypes , basicArgValues , & applicationArgs )
11531249 if err != nil {
11541250 reportErrorf ("cannot parse arguments to ABI encoding: %v" , err )
0 commit comments