summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHang Su <87964331+ahangsu@users.noreply.github.com>2022-06-30 17:14:27 -0400
committerGitHub <noreply@github.com>2022-06-30 17:14:27 -0400
commitf59d3acd7b9c3f1b6bcf7df19e24fd0850c7b94e (patch)
treea8f6426e9d80bccce0015c9dca8ffc1bacfcda4e
parent43435b7c2ff8ea5d6e7792f60a341200e50cc788 (diff)
parenta1553588f74aeaaafde89809e8515ea659f3e649 (diff)
Merge pull request #4183 from algochoi/algochoi/box-search-apiahangsu/box-names-by-app-id
Algod: Modify Box Search API to take name as query parameter
-rw-r--r--cmd/goal/application.go98
-rw-r--r--cmd/goal/formatting_test.go19
-rw-r--r--cmd/goal/interact.go4
-rw-r--r--daemon/algod/api/algod.oas2.json14
-rw-r--r--daemon/algod/api/algod.oas3.yml70
-rw-r--r--daemon/algod/api/client/restClient.go10
-rw-r--r--daemon/algod/api/server/v2/generated/private/routes.go34
-rw-r--r--daemon/algod/api/server/v2/generated/routes.go463
-rw-r--r--daemon/algod/api/server/v2/generated/types.go7
-rw-r--r--daemon/algod/api/server/v2/handlers.go18
-rw-r--r--data/transactions/logic/parsing.go105
-rw-r--r--data/transactions/logic/parsing_test.go49
-rw-r--r--libgoal/libgoal.go9
-rw-r--r--test/e2e-go/restAPI/restClient_test.go54
14 files changed, 556 insertions, 398 deletions
diff --git a/cmd/goal/application.go b/cmd/goal/application.go
index 08497552d..bf0ca9230 100644
--- a/cmd/goal/application.go
+++ b/cmd/goal/application.go
@@ -19,9 +19,6 @@ package main
import (
"bytes"
"crypto/sha512"
- "encoding/base32"
- "encoding/base64"
- "encoding/binary"
"encoding/hex"
"errors"
"fmt"
@@ -195,33 +192,25 @@ func init() {
methodAppCmd.Flags().MarkHidden("app-arg") // nolint:errcheck
}
-type appCallBytes struct {
- Encoding string `codec:"encoding"`
- Value string `codec:"value"`
-}
-
-func newAppCallBytes(arg string) appCallBytes {
- parts := strings.SplitN(arg, ":", 2)
- if len(parts) != 2 {
- reportErrorf("all arguments and box names should be of the form 'encoding:value'")
- }
- return appCallBytes{
- Encoding: parts[0],
- Value: parts[1],
+func newAppCallBytes(arg string) logic.AppCallBytes {
+ appBytes, err := logic.NewAppCallBytes(arg)
+ if err != nil {
+ reportErrorf(err.Error())
}
+ return appBytes
}
type appCallInputs struct {
- Accounts []string `codec:"accounts"`
- ForeignApps []uint64 `codec:"foreignapps"`
- ForeignAssets []uint64 `codec:"foreignassets"`
- Boxes []boxRef `codec:"boxes"`
- Args []appCallBytes `codec:"args"`
+ Accounts []string `codec:"accounts"`
+ ForeignApps []uint64 `codec:"foreignapps"`
+ ForeignAssets []uint64 `codec:"foreignassets"`
+ Boxes []boxRef `codec:"boxes"`
+ Args []logic.AppCallBytes `codec:"args"`
}
type boxRef struct {
- appID uint64 `codec:"app"`
- name appCallBytes `codec:"name"`
+ appID uint64 `codec:"app"`
+ name logic.AppCallBytes `codec:"name"`
}
// newBoxRef parses a command-line box ref, which is an optional appId, a comma,
@@ -270,67 +259,10 @@ func stringsToBoxRefs(strs []string) []boxRef {
return out
}
-func (arg appCallBytes) raw() (rawValue []byte, parseErr error) {
- switch arg.Encoding {
- case "str", "string":
- rawValue = []byte(arg.Value)
- case "int", "integer":
- num, err := strconv.ParseUint(arg.Value, 10, 64)
- if err != nil {
- parseErr = fmt.Errorf("Could not parse uint64 from string (%s): %v", arg.Value, err)
- return
- }
- ibytes := make([]byte, 8)
- binary.BigEndian.PutUint64(ibytes, num)
- rawValue = ibytes
- case "addr", "address":
- addr, err := basics.UnmarshalChecksumAddress(arg.Value)
- if err != nil {
- parseErr = fmt.Errorf("Could not unmarshal checksummed address from string (%s): %v", arg.Value, err)
- return
- }
- rawValue = addr[:]
- case "b32", "base32", "byte base32":
- data, err := base32.StdEncoding.DecodeString(arg.Value)
- if err != nil {
- parseErr = fmt.Errorf("Could not decode base32-encoded string (%s): %v", arg.Value, err)
- return
- }
- rawValue = data
- case "b64", "base64", "byte base64":
- data, err := base64.StdEncoding.DecodeString(arg.Value)
- if err != nil {
- parseErr = fmt.Errorf("Could not decode base64-encoded string (%s): %v", arg.Value, err)
- return
- }
- rawValue = data
- case "abi":
- typeAndValue := strings.SplitN(arg.Value, ":", 2)
- if len(typeAndValue) != 2 {
- parseErr = fmt.Errorf("Could not decode abi string (%s): should split abi-type and abi-value with colon", arg.Value)
- return
- }
- abiType, err := abi.TypeOf(typeAndValue[0])
- if err != nil {
- parseErr = fmt.Errorf("Could not decode abi type string (%s): %v", typeAndValue[0], err)
- return
- }
- value, err := abiType.UnmarshalFromJSON([]byte(typeAndValue[1]))
- if err != nil {
- parseErr = fmt.Errorf("Could not decode abi value string (%s):%v ", typeAndValue[1], err)
- return
- }
- return abiType.Encode(value)
- default:
- parseErr = fmt.Errorf("Unknown encoding: %s", arg.Encoding)
- }
- return
-}
-
func translateBoxRefs(input []boxRef, foreignApps []uint64) []transactions.BoxRef {
output := make([]transactions.BoxRef, len(input))
for i, tbr := range input {
- rawName, err := tbr.name.raw()
+ rawName, err := tbr.name.Raw()
if err != nil {
reportErrorf("Could not decode box name %s: %v", tbr.name, err)
}
@@ -372,7 +304,7 @@ func parseAppInputs(inputs appCallInputs) (args [][]byte, accounts []string, for
boxes = translateBoxRefs(inputs.Boxes, foreignApps)
args = make([][]byte, len(inputs.Args))
for i, arg := range inputs.Args {
- rawValue, err := arg.raw()
+ rawValue, err := arg.Raw()
if err != nil {
reportErrorf("Could not decode input at index %d: %v", i, err)
}
@@ -410,7 +342,7 @@ func getAppInputs() (args [][]byte, accounts []string, apps []uint64, assets []u
// on it. appArgs became `StringArrayVar` in order to support abi arguments
// which contain commas.
- var encodedArgs []appCallBytes
+ var encodedArgs []logic.AppCallBytes
for _, arg := range appArgs {
if len(arg) > 0 {
encodedArgs = append(encodedArgs, newAppCallBytes(arg))
diff --git a/cmd/goal/formatting_test.go b/cmd/goal/formatting_test.go
index 725044ebe..ab42e285d 100644
--- a/cmd/goal/formatting_test.go
+++ b/cmd/goal/formatting_test.go
@@ -45,23 +45,14 @@ func TestUnicodePrintable(t *testing.T) {
func TestNewAppCallBytes(t *testing.T) {
partitiontest.PartitionTest(t)
- acb := newAppCallBytes("str:hello")
- require.Equal(t, "str", acb.Encoding)
- require.Equal(t, "hello", acb.Value)
- _, err := acb.raw()
- require.NoError(t, err)
-
- require.Panics(t, func() { newAppCallBytes("hello") })
- acb = newAppCallBytes("str:1:2")
- require.Equal(t, "str", acb.Encoding)
- require.Equal(t, "1:2", acb.Value)
- _, err = acb.raw()
+ acb := newAppCallBytes("int:3")
+ require.Equal(t, "int", acb.Encoding)
+ require.Equal(t, "3", acb.Value)
+ _, err := acb.Raw()
require.NoError(t, err)
- acb = newAppCallBytes(":x")
- _, err = acb.raw()
- require.Error(t, err)
+ require.Panics(t, func() { newAppCallBytes("hello") })
}
func TestNewBoxRef(t *testing.T) {
diff --git a/cmd/goal/interact.go b/cmd/goal/interact.go
index 8677f4738..caf4db717 100644
--- a/cmd/goal/interact.go
+++ b/cmd/goal/interact.go
@@ -512,7 +512,7 @@ var appExecuteCmd = &cobra.Command{
var inputs appCallInputs
for _, arg := range proc.Args {
- var callArg appCallBytes
+ var callArg logic.AppCallBytes
callArg.Encoding = arg.Kind
if !procFlags.Changed(arg.Name) && arg.Default != "" {
@@ -564,7 +564,7 @@ var appExecuteCmd = &cobra.Command{
appArgs := make([][]byte, len(inputs.Args))
for i, arg := range inputs.Args {
- rawValue, err := arg.raw()
+ rawValue, err := arg.Raw()
if err != nil {
reportErrorf("Could not parse argument corresponding to '%s': %v", proc.Args[i].Name, err)
}
diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json
index df624fc33..ea7c5651a 100644
--- a/daemon/algod/api/algod.oas2.json
+++ b/daemon/algod/api/algod.oas2.json
@@ -1372,9 +1372,9 @@
}
]
},
- "/v2/applications/{application-id}/boxes/{box-name}": {
+ "/v2/applications/{application-id}/box": {
"get": {
- "description": "Given an application ID and box name, it returns the box name and value (each base64 encoded).",
+ "description": "Given an application ID and box name, it returns the box name and value (each base64 encoded). Box names must be in the goal app call arg encoding form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.",
"produces": [
"application/json"
],
@@ -1393,9 +1393,9 @@
},
{
"type": "string",
- "description": "A box name",
- "name": "box-name",
- "in": "path",
+ "description": "A box name, in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.",
+ "name": "name",
+ "in": "query",
"required": true
}
],
@@ -1442,8 +1442,8 @@
},
{
"type": "string",
- "name": "box-name",
- "in": "path",
+ "name": "name",
+ "in": "query",
"required": true
}
]
diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml
index d622baf1e..822a074a8 100644
--- a/daemon/algod/api/algod.oas3.yml
+++ b/daemon/algod/api/algod.oas3.yml
@@ -2424,10 +2424,10 @@
"summary": "Get application information."
}
},
- "/v2/applications/{application-id}/boxes": {
+ "/v2/applications/{application-id}/box": {
"get": {
- "description": "Given an application ID, it returns the box names of that application. No particular ordering is guaranteed.",
- "operationId": "GetApplicationBoxes",
+ "description": "Given an application ID and box name, it returns the box name and value (each base64 encoded). Box names must be in the goal app call arg encoding form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.",
+ "operationId": "GetApplicationBoxByName",
"parameters": [
{
"description": "An application identifier",
@@ -2439,11 +2439,12 @@
}
},
{
- "description": "Max number of box names to return. If max is not set, or max == 0, returns all box-names.",
+ "description": "A box name, in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.",
"in": "query",
- "name": "max",
+ "name": "name",
+ "required": true,
"schema": {
- "type": "integer"
+ "type": "string"
}
}
],
@@ -2452,16 +2453,11 @@
"content": {
"application/json": {
"schema": {
- "items": {
- "format": "byte",
- "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
- "type": "string"
- },
- "type": "array"
+ "$ref": "#/components/schemas/Box"
}
}
},
- "description": "Box names of an application"
+ "description": "Box information"
},
"400": {
"content": {
@@ -2483,6 +2479,16 @@
},
"description": "Invalid API Token"
},
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Box Not Found"
+ },
"500": {
"content": {
"application/json": {
@@ -2498,13 +2504,13 @@
"description": "Unknown Error"
}
},
- "summary": "Get box names for a given application."
+ "summary": "Get box information for a given application."
}
},
- "/v2/applications/{application-id}/boxes/{box-name}": {
+ "/v2/applications/{application-id}/boxes": {
"get": {
- "description": "Given an application ID and box name, it returns the box name and value (each base64 encoded).",
- "operationId": "GetApplicationBoxByName",
+ "description": "Given an application ID, it returns the box names of that application. No particular ordering is guaranteed.",
+ "operationId": "GetApplicationBoxes",
"parameters": [
{
"description": "An application identifier",
@@ -2516,12 +2522,11 @@
}
},
{
- "description": "A box name",
- "in": "path",
- "name": "box-name",
- "required": true,
+ "description": "Max number of box names to return. If max is not set, or max == 0, returns all box-names.",
+ "in": "query",
+ "name": "max",
"schema": {
- "type": "string"
+ "type": "integer"
}
}
],
@@ -2530,11 +2535,16 @@
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/Box"
+ "items": {
+ "format": "byte",
+ "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$",
+ "type": "string"
+ },
+ "type": "array"
}
}
},
- "description": "Box information"
+ "description": "Box names of an application"
},
"400": {
"content": {
@@ -2556,16 +2566,6 @@
},
"description": "Invalid API Token"
},
- "404": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- },
- "description": "Box Not Found"
- },
"500": {
"content": {
"application/json": {
@@ -2581,7 +2581,7 @@
"description": "Unknown Error"
}
},
- "summary": "Get box information for a given application."
+ "summary": "Get box names for a given application."
}
},
"/v2/assets/{asset-id}": {
diff --git a/daemon/algod/api/client/restClient.go b/daemon/algod/api/client/restClient.go
index b44ceff80..19d142967 100644
--- a/daemon/algod/api/client/restClient.go
+++ b/daemon/algod/api/client/restClient.go
@@ -428,6 +428,16 @@ func (client RestClient) ApplicationBoxes(appID uint64) (response generatedV2.Bo
return
}
+type applicationBoxByNameParams struct {
+ Name string `url:"name"`
+}
+
+// GetApplicationBoxByName gets the BoxResponse associated with the passed application ID and box name
+func (client RestClient) GetApplicationBoxByName(appID uint64, name string) (response generatedV2.BoxResponse, err error) {
+ err = client.get(&response, fmt.Sprintf("/v2/applications/%d/box", appID), applicationBoxByNameParams{name})
+ return
+}
+
// AccountInformationV2 gets the AccountData associated with the passed address
func (client RestClient) AccountInformationV2(address string, includeCreatables bool) (response generatedV2.Account, err error) {
var infoParams accountInformationParams
diff --git a/daemon/algod/api/server/v2/generated/private/routes.go b/daemon/algod/api/server/v2/generated/private/routes.go
index 9cb47a1b0..cc0191404 100644
--- a/daemon/algod/api/server/v2/generated/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/private/routes.go
@@ -445,23 +445,23 @@ var swaggerSpec = []string{
"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",
- "mn9uqfHZnp5YCmf+2Wd47W7dSqFy5ougw0godjWbL8QG1LUazz8vxAa99uEkw+uyD+/NP6PSOfh7e62f",
- "9cbM521crod7wGr+uXlR7soe9Rxi9ikbXUeDB+imhLmXjZX91Zxun5nBVPsBwppUTzJDoqbXq/p1vaAo",
- "xeGHnoxnByJ+JDzPhlib49aaqeGoWlYQ1kmo74tW++bW+HCQvPz0+cn0ycHVX8yt4P588exqpKG5eUCZ",
- "nNYsf2TDT5jWgCoznsKnBwf/zZ6ffn7NFe8U7Fu+uNiD4DQjPuAU535yf3OfcDTzG+5M7O1zNZ28uM/V",
- "n3BD8jQn2DLIp+tv/S/8nItL7lsaUaEqCiq3/hirFlPwb2bihURXCtU8yS6ohskntCPEIhMGmAu+831t",
- "5oKPl39lLvfFXL6MV92fXvOAf/kr/spOvzR2emrZ3Xh26kQ5m9Mwty/7NBJer2zzCqLJFZjmQHe9Y9nl",
- "sD+A7j3LObkli/nTXuj8731Onh88vz8I2jVHf4QteSs0+R59a1/omR13fHZJQh3NKMt6RG7ZPyj9nci2",
- "OzBUqFXp4pAjcsmCcQNy/3bpv3nTezbzHLbE+pu9X8E9G92Wh65uyQO+2Bc+v/KQrzxE2umf3d/0pyAv",
- "WArkDIpSSCpZviW/8DqL7OZqXZZFY/naR7/H04w2kooMVsATx7CShci2vgxUa8BzsPbvnqAy/9yu5WrN",
- "X4NmqWP8vX5iqg/0YktOjnsSjO3W5bTfbbFpR2OM6IRdEHdqhl1eNKCM7SJzs5CV0MRiIXOL+sp4vjKe",
- "Wwkvow9PTH6JahPekNO9k6c+nTpWNYLq/tRjdI4/9bjeyUb39ZmY/mJjHiEjwQdbDqWL5q8s4StLuB1L",
- "+AEihxFPrWMSEaK7iaW3zyAwvCvrvoiAMRK+eZVTSRSMNVMc4YjOOHEfXOK+lbQorqyORjmBDVP4wk9k",
- "w+5Wb/vK4r6yuC/Ia7Wf0bQFkWtrOuewLWhZ6zdqXelMXNoyRFGuiGWWae5qMmKVxDrcQwviB2iyqMjP",
- "Lm0w35olXLDMiHGaFWBEqprXmc4+NrYJzjUjNE9jrhjHCZBV4Cy2+CgN8hMUpILbh+Q6vjYH2VurE8aY",
- "7O8VIEdzuHEwTqYtZ4vbxkipz1vLX33fyNUOW3r9Glzr7/klZTpZCunSkxBD/SgMDTSfu4IbnV+b5NHe",
- "F8yIDX4MYjfiv87r6tfRj93QlthXFxTiGzWxa2EsGO5hHQX24ZPZCiye6La3CW06nM8xpn8tlJ5Prqaf",
- "O2FP4cdPNfY/1zev24WrT1f/PwAA//9t3Heg8LUAAA==",
+ "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",
+ "Gvuf65vX7cLVp6v/HwAA//84pB4p47UAAA==",
}
// GetSwagger returns the Swagger specification corresponding to the generated code
diff --git a/daemon/algod/api/server/v2/generated/routes.go b/daemon/algod/api/server/v2/generated/routes.go
index afe0dc119..f2ac89364 100644
--- a/daemon/algod/api/server/v2/generated/routes.go
+++ b/daemon/algod/api/server/v2/generated/routes.go
@@ -32,12 +32,12 @@ type ServerInterface interface {
// Get application information.
// (GET /v2/applications/{application-id})
GetApplicationByID(ctx echo.Context, applicationId uint64) error
+ // Get box information for a given application.
+ // (GET /v2/applications/{application-id}/box)
+ GetApplicationBoxByName(ctx echo.Context, applicationId uint64, params GetApplicationBoxByNameParams) error
// Get box names for a given application.
// (GET /v2/applications/{application-id}/boxes)
GetApplicationBoxes(ctx echo.Context, applicationId uint64, params GetApplicationBoxesParams) error
- // Get box information for a given application.
- // (GET /v2/applications/{application-id}/boxes/{box-name})
- GetApplicationBoxByName(ctx echo.Context, applicationId uint64, boxName string) error
// Get asset information.
// (GET /v2/assets/{asset-id})
GetAssetByID(ctx echo.Context, assetId uint64) error
@@ -324,12 +324,12 @@ func (w *ServerInterfaceWrapper) GetApplicationByID(ctx echo.Context) error {
return err
}
-// GetApplicationBoxes converts echo context to params.
-func (w *ServerInterfaceWrapper) GetApplicationBoxes(ctx echo.Context) error {
+// GetApplicationBoxByName converts echo context to params.
+func (w *ServerInterfaceWrapper) GetApplicationBoxByName(ctx echo.Context) error {
validQueryParams := map[string]bool{
"pretty": true,
- "max": true,
+ "name": true,
}
// Check for unknown query parameters.
@@ -351,27 +351,30 @@ func (w *ServerInterfaceWrapper) GetApplicationBoxes(ctx echo.Context) error {
ctx.Set("api_key.Scopes", []string{""})
// Parameter object where we will unmarshal all parameters from the context
- var params GetApplicationBoxesParams
- // ------------- Optional query parameter "max" -------------
- if paramValue := ctx.QueryParam("max"); paramValue != "" {
+ var params GetApplicationBoxByNameParams
+ // ------------- Required query parameter "name" -------------
+ if paramValue := ctx.QueryParam("name"); paramValue != "" {
+ } else {
+ return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Query argument name is required, but not found"))
}
- err = runtime.BindQueryParameter("form", true, false, "max", ctx.QueryParams(), &params.Max)
+ err = runtime.BindQueryParameter("form", true, true, "name", ctx.QueryParams(), &params.Name)
if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter max: %s", err))
+ return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter name: %s", err))
}
// Invoke the callback with all the unmarshalled arguments
- err = w.Handler.GetApplicationBoxes(ctx, applicationId, params)
+ err = w.Handler.GetApplicationBoxByName(ctx, applicationId, params)
return err
}
-// GetApplicationBoxByName converts echo context to params.
-func (w *ServerInterfaceWrapper) GetApplicationBoxByName(ctx echo.Context) error {
+// GetApplicationBoxes converts echo context to params.
+func (w *ServerInterfaceWrapper) GetApplicationBoxes(ctx echo.Context) error {
validQueryParams := map[string]bool{
"pretty": true,
+ "max": true,
}
// Check for unknown query parameters.
@@ -390,18 +393,22 @@ func (w *ServerInterfaceWrapper) GetApplicationBoxByName(ctx echo.Context) error
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter application-id: %s", err))
}
- // ------------- Path parameter "box-name" -------------
- var boxName string
+ ctx.Set("api_key.Scopes", []string{""})
+
+ // Parameter object where we will unmarshal all parameters from the context
+ var params GetApplicationBoxesParams
+ // ------------- Optional query parameter "max" -------------
+ if paramValue := ctx.QueryParam("max"); paramValue != "" {
- err = runtime.BindStyledParameter("simple", false, "box-name", ctx.Param("box-name"), &boxName)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter box-name: %s", err))
}
- ctx.Set("api_key.Scopes", []string{""})
+ err = runtime.BindQueryParameter("form", true, false, "max", ctx.QueryParams(), &params.Max)
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter max: %s", err))
+ }
// Invoke the callback with all the unmarshalled arguments
- err = w.Handler.GetApplicationBoxByName(ctx, applicationId, boxName)
+ err = w.Handler.GetApplicationBoxes(ctx, applicationId, params)
return err
}
@@ -856,8 +863,8 @@ func RegisterHandlers(router interface {
router.GET("/v2/accounts/:address/assets/:asset-id", wrapper.AccountAssetInformation, m...)
router.GET("/v2/accounts/:address/transactions/pending", wrapper.GetPendingTransactionsByAddress, m...)
router.GET("/v2/applications/:application-id", wrapper.GetApplicationByID, m...)
+ router.GET("/v2/applications/:application-id/box", wrapper.GetApplicationBoxByName, m...)
router.GET("/v2/applications/:application-id/boxes", wrapper.GetApplicationBoxes, m...)
- router.GET("/v2/applications/:application-id/boxes/:box-name", wrapper.GetApplicationBoxByName, m...)
router.GET("/v2/assets/:asset-id", wrapper.GetAssetByID, m...)
router.GET("/v2/blocks/:round", wrapper.GetBlock, m...)
router.GET("/v2/blocks/:round/transactions/:txid/proof", wrapper.GetProof, m...)
@@ -877,211 +884,213 @@ func RegisterHandlers(router interface {
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
+ "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",
}
// GetSwagger returns the Swagger specification corresponding to the generated code
diff --git a/daemon/algod/api/server/v2/generated/types.go b/daemon/algod/api/server/v2/generated/types.go
index b6448a196..3447dd37d 100644
--- a/daemon/algod/api/server/v2/generated/types.go
+++ b/daemon/algod/api/server/v2/generated/types.go
@@ -830,6 +830,13 @@ type GetPendingTransactionsByAddressParams struct {
Format *string `json:"format,omitempty"`
}
+// GetApplicationBoxByNameParams defines parameters for GetApplicationBoxByName.
+type GetApplicationBoxByNameParams struct {
+
+ // A box name, in the goal app call arg form 'encoding:value'. For ints, use the form 'int:1234'. For raw bytes, use the form 'b64:A=='. For printable strings, use the form 'str:hello'. For addresses, use the form 'addr:XYZ...'.
+ Name string `json:"name"`
+}
+
// GetApplicationBoxesParams defines parameters for GetApplicationBoxes.
type GetApplicationBoxesParams struct {
diff --git a/daemon/algod/api/server/v2/handlers.go b/daemon/algod/api/server/v2/handlers.go
index 5c9a8820a..e7f737d51 100644
--- a/daemon/algod/api/server/v2/handlers.go
+++ b/daemon/algod/api/server/v2/handlers.go
@@ -24,7 +24,6 @@ import (
"io"
"math"
"net/http"
- "net/url"
"strings"
"time"
@@ -1174,25 +1173,30 @@ func (v2 *Handlers) GetApplicationBoxes(ctx echo.Context, applicationID uint64,
}
// GetApplicationBoxByName returns the value of an application's box
-// (GET /v2/applications/{application-id}/boxes/{box-name})
-func (v2 *Handlers) GetApplicationBoxByName(ctx echo.Context, applicationID uint64, boxName string) error {
+// (GET /v2/applications/{application-id}/box)
+func (v2 *Handlers) GetApplicationBoxByName(ctx echo.Context, applicationID uint64, params generated.GetApplicationBoxByNameParams) error {
appIdx := basics.AppIndex(applicationID)
ledger := v2.Node.LedgerForAPI()
-
lastRound := ledger.Latest()
- boxName, err := url.PathUnescape(boxName)
+ encodedBoxName := params.Name
+ boxNameBytes, err := logic.NewAppCallBytes(encodedBoxName)
if err != nil {
return badRequest(ctx, err, err.Error(), v2.Log)
}
- value, err := ledger.LookupKv(lastRound, logic.MakeBoxKey(appIdx, boxName))
+ boxName, err := boxNameBytes.Raw()
if err != nil {
- return internalError(ctx, err, errFailedLookingUpLedger, v2.Log)
+ return badRequest(ctx, err, err.Error(), v2.Log)
}
+ value, err := ledger.LookupKv(lastRound, logic.MakeBoxKey(appIdx, string(boxName)))
+ if err != nil {
+ return internalError(ctx, err, errFailedLookingUpLedger, v2.Log)
+ }
if value == nil {
return notFound(ctx, errors.New(errBoxDoesNotExist), errBoxDoesNotExist, v2.Log)
}
+
response := generated.BoxResponse{
Name: []byte(boxName),
Value: []byte(*value),
diff --git a/data/transactions/logic/parsing.go b/data/transactions/logic/parsing.go
new file mode 100644
index 000000000..95526ec19
--- /dev/null
+++ b/data/transactions/logic/parsing.go
@@ -0,0 +1,105 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package logic
+
+import (
+ "encoding/base32"
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/algorand/go-algorand/data/abi"
+ "github.com/algorand/go-algorand/data/basics"
+)
+
+// AppCallBytes represents an encoding and a value of an app call argument.
+type AppCallBytes struct {
+ Encoding string `codec:"encoding"`
+ Value string `codec:"value"`
+}
+
+// NewAppCallBytes parses an argument of "form encoding:value" to AppCallBytes.
+func NewAppCallBytes(arg string) (AppCallBytes, error) {
+ parts := strings.SplitN(arg, ":", 2)
+ if len(parts) != 2 {
+ return AppCallBytes{}, fmt.Errorf("all arguments and box names should be of the form 'encoding:value'")
+ }
+ return AppCallBytes{
+ Encoding: parts[0],
+ Value: parts[1],
+ }, nil
+}
+
+// Raw converts an AppCallBytes arg to a byte array.
+func (arg AppCallBytes) Raw() (rawValue []byte, parseErr error) {
+ switch arg.Encoding {
+ case "str", "string":
+ rawValue = []byte(arg.Value)
+ case "int", "integer":
+ num, err := strconv.ParseUint(arg.Value, 10, 64)
+ if err != nil {
+ parseErr = fmt.Errorf("Could not parse uint64 from string (%s): %v", arg.Value, err)
+ return
+ }
+ ibytes := make([]byte, 8)
+ binary.BigEndian.PutUint64(ibytes, num)
+ rawValue = ibytes
+ case "addr", "address":
+ addr, err := basics.UnmarshalChecksumAddress(arg.Value)
+ if err != nil {
+ parseErr = fmt.Errorf("Could not unmarshal checksummed address from string (%s): %v", arg.Value, err)
+ return
+ }
+ rawValue = addr[:]
+ case "b32", "base32", "byte base32":
+ data, err := base32.StdEncoding.DecodeString(arg.Value)
+ if err != nil {
+ parseErr = fmt.Errorf("Could not decode base32-encoded string (%s): %v", arg.Value, err)
+ return
+ }
+ rawValue = data
+ case "b64", "base64", "byte base64":
+ data, err := base64.StdEncoding.DecodeString(arg.Value)
+ if err != nil {
+ parseErr = fmt.Errorf("Could not decode base64-encoded string (%s): %v", arg.Value, err)
+ return
+ }
+ rawValue = data
+ case "abi":
+ typeAndValue := strings.SplitN(arg.Value, ":", 2)
+ if len(typeAndValue) != 2 {
+ parseErr = fmt.Errorf("Could not decode abi string (%s): should split abi-type and abi-value with colon", arg.Value)
+ return
+ }
+ abiType, err := abi.TypeOf(typeAndValue[0])
+ if err != nil {
+ parseErr = fmt.Errorf("Could not decode abi type string (%s): %v", typeAndValue[0], err)
+ return
+ }
+ value, err := abiType.UnmarshalFromJSON([]byte(typeAndValue[1]))
+ if err != nil {
+ parseErr = fmt.Errorf("Could not decode abi value string (%s):%v ", typeAndValue[1], err)
+ return
+ }
+ return abiType.Encode(value)
+ default:
+ parseErr = fmt.Errorf("Unknown encoding: %s", arg.Encoding)
+ }
+ return
+}
diff --git a/data/transactions/logic/parsing_test.go b/data/transactions/logic/parsing_test.go
new file mode 100644
index 000000000..5fbe7f55d
--- /dev/null
+++ b/data/transactions/logic/parsing_test.go
@@ -0,0 +1,49 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see <https://www.gnu.org/licenses/>.
+
+package logic
+
+import (
+ "testing"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewAppCallBytes(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ acb, err := NewAppCallBytes("str:hello")
+ require.NoError(t, err)
+ require.Equal(t, "str", acb.Encoding)
+ require.Equal(t, "hello", acb.Value)
+ _, err = acb.Raw()
+ require.NoError(t, err)
+
+ acb, err = NewAppCallBytes("hello")
+ require.Error(t, err)
+
+ acb, err = NewAppCallBytes("str:1:2")
+ require.Equal(t, "str", acb.Encoding)
+ require.Equal(t, "1:2", acb.Value)
+ _, err = acb.Raw()
+ require.NoError(t, err)
+
+ acb, err = NewAppCallBytes(":x")
+ _, err = acb.Raw()
+ require.Error(t, err)
+}
diff --git a/libgoal/libgoal.go b/libgoal/libgoal.go
index 722e3c72b..798d93bf7 100644
--- a/libgoal/libgoal.go
+++ b/libgoal/libgoal.go
@@ -785,6 +785,15 @@ func (c *Client) ApplicationBoxes(index uint64) (resp generatedV2.BoxesResponse,
return
}
+// GetApplicationBoxByName takes an app's index and box name and returns its value
+func (c *Client) GetApplicationBoxByName(index uint64, name string) (resp generatedV2.BoxResponse, err error) {
+ algod, err := c.ensureAlgodClient()
+ if err == nil {
+ resp, err = algod.GetApplicationBoxByName(index, name)
+ }
+ return
+}
+
// TransactionInformation takes an address and associated txid and return its information
func (c *Client) TransactionInformation(addr, txid string) (resp v1.Transaction, err error) {
algod, err := c.ensureAlgodClient()
diff --git a/test/e2e-go/restAPI/restClient_test.go b/test/e2e-go/restAPI/restClient_test.go
index 4c9b5de41..e227aae8f 100644
--- a/test/e2e-go/restAPI/restClient_test.go
+++ b/test/e2e-go/restAPI/restClient_test.go
@@ -18,10 +18,10 @@ package restapi
import (
"context"
+ "encoding/binary"
"encoding/hex"
"errors"
"flag"
- "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated"
"math"
"math/rand"
"os"
@@ -31,6 +31,8 @@ import (
"time"
"unicode"
+ "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated"
+
"github.com/stretchr/testify/require"
"github.com/algorand/go-algorand/config"
@@ -1268,10 +1270,20 @@ del: // delete box arg[1]
txn ApplicationArgs 0 // [arg[0]]
byte "delete" // [arg[0], "delete"]
== // [arg[0]=?="delete"]
- bz bad // "delete" ? continue : goto bad
+ bz set // "delete" ? continue : goto set
txn ApplicationArgs 1 // [arg[1]]
box_del // del boxes[arg[1]]
b end
+set: // put arg[1] at start of box arg[0] ... so actually a _partial_ "set"
+ txn ApplicationArgs 0 // [arg[0]]
+ byte "set" // [arg[0], "set"]
+ == // [arg[0]=?="set"]
+ bz bad // "delete" ? continue : goto bad
+ txn ApplicationArgs 1 // [arg[1]]
+ int 0 // [arg[1], 0]
+ txn ApplicationArgs 2 // [arg[1], 0, arg[2]]
+ box_replace // [] // boxes: arg[1] -> replace(boxes[arg[1]], 0, arg[2])
+ b end
bad:
err
end:
@@ -1320,7 +1332,7 @@ end:
var createdBoxCount uint64 = 0
// define operate box helper
- operateBoxAndSendTxn := func(operation string, boxNames []string) {
+ operateBoxAndSendTxn := func(operation string, boxNames []string, boxValues []string) {
txns := make([]transactions.Transaction, len(boxNames))
txIDs := make(map[string]string, len(boxNames))
@@ -1328,6 +1340,7 @@ end:
appArgs := [][]byte{
[]byte(operation),
[]byte(boxNames[i]),
+ []byte(boxValues[i]),
}
boxRef := transactions.BoxRef{
Name: []byte(boxNames[i]),
@@ -1370,21 +1383,24 @@ end:
// then submit transaction group containing all operations on box names
// Then we check these boxes are appropriately created/deleted
operateAndMatchRes := func(operation string, boxNames []string) {
+ boxValues := make([]string, len(boxNames))
if operation == "create" {
- for _, box := range boxNames {
+ for i, box := range boxNames {
keyValid, ok := createdBoxName[box]
a.False(ok && keyValid)
+ boxValues[i] = ""
}
} else if operation == "delete" {
- for _, box := range boxNames {
+ for i, box := range boxNames {
keyValid, ok := createdBoxName[box]
a.True(keyValid == ok)
+ boxValues[i] = ""
}
} else {
a.True(false)
}
- operateBoxAndSendTxn(operation, boxNames)
+ operateBoxAndSendTxn(operation, boxNames, boxValues)
if operation == "create" {
for _, box := range boxNames {
@@ -1474,4 +1490,30 @@ end:
resp, err = testClient.ApplicationBoxes(uint64(createdAppID))
a.NoError(err)
a.Empty(resp)
+
+ // Get Box value from box name
+ encodeInt := func(n uint64) []byte {
+ ibytes := make([]byte, 8)
+ binary.BigEndian.PutUint64(ibytes, n)
+ return ibytes
+ }
+
+ boxTests := [][]interface{}{
+ {[]byte("foo"), "str:foo", []byte("bar12")},
+ {encodeInt(12321), "int:12321", []byte{0, 1, 254, 3, 2}},
+ {[]byte{0, 248, 255, 32}, "b64:APj/IA==", []byte("lux56")},
+ }
+ for _, boxTest := range boxTests {
+ boxName := boxTest[0].([]byte)
+ encodedName := boxTest[1].(string)
+ // Box values are 5 bytes, as defined by the test TEAL program.
+ boxValue := boxTest[2].([]byte)
+ operateBoxAndSendTxn("create", []string{string(boxName)}, []string{""})
+ operateBoxAndSendTxn("set", []string{string(boxName)}, []string{string(boxValue)})
+
+ boxResponse, err := testClient.GetApplicationBoxByName(uint64(createdAppID), encodedName)
+ a.NoError(err)
+ a.Equal(boxName, boxResponse.Name)
+ a.Equal(boxValue, boxResponse.Value)
+ }
}