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: 22 additions & 0 deletions sdk/core/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,28 @@ func CoerceArg(v interface{}) (interface{}, error) {
return "0x" + hex.EncodeToString(val), nil
case *big.Int:
return BigIntArg(val).ToJSON(), nil
case []interface{}:
// list / tuple: coerce each element recursively.
out := make([]interface{}, len(val))
for i, e := range val {
c, err := CoerceArg(e)
if err != nil {
return nil, err
}
out[i] = c
}
return out, nil
case map[string]interface{}:
// map / record: coerce each value recursively.
out := make(map[string]interface{}, len(val))
for k, e := range val {
c, err := CoerceArg(e)
if err != nil {
return nil, err
}
out[k] = c
}
return out, nil
default:
return nil, fmt.Errorf("unsupported arg type: %T", v)
}
Expand Down
21 changes: 21 additions & 0 deletions sdk/core/args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ func TestCoerceArgUnsupportedType(t *testing.T) {
}
}

func TestCoerceArgRecursesIntoCompounds(t *testing.T) {
// list/tuple: a []byte nested in a slice must still hex-encode.
got, err := core.CoerceArg([]interface{}{1, []byte{0xab, 0xcd}})
if err != nil {
t.Fatalf("CoerceArg list: %v", err)
}
list := got.([]interface{})
if list[0].(int64) != 1 || list[1].(string) != "0xabcd" {
t.Fatalf("unexpected list coercion: %#v", list)
}

// map/record: nested []byte value must hex-encode too.
got, err = core.CoerceArg(map[string]interface{}{"policy": []byte{0x01}})
if err != nil {
t.Fatalf("CoerceArg map: %v", err)
}
if got.(map[string]interface{})["policy"].(string) != "0x01" {
t.Fatalf("unexpected map coercion: %#v", got)
}
}

func TestNormalizeArgKey(t *testing.T) {
if core.NormalizeArgKey("Quantity") != "quantity" {
t.Error("expected lowercase")
Expand Down
4 changes: 0 additions & 4 deletions sdk/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ func TestErrorDiscriminationTII(t *testing.T) {
assertDiscriminable[*tii.InvalidJSONError](t, &tii.InvalidJSONError{Cause: fmt.Errorf("bad")})
assertDiscriminable[*tii.UnknownTxError](t, &tii.UnknownTxError{Name: "foo"})
assertDiscriminable[*tii.UnknownProfileError](t, &tii.UnknownProfileError{Name: "bar"})
assertDiscriminable[*tii.InvalidParamsSchemaError](t, &tii.InvalidParamsSchemaError{Detail: "bad"})
assertDiscriminable[*tii.InvalidParamTypeError](t, &tii.InvalidParamTypeError{Detail: "bad"})
}

func TestErrorDiscriminationTRP(t *testing.T) {
Expand Down Expand Up @@ -102,8 +100,6 @@ func TestTiiErrorMarker(t *testing.T) {
var _ tii.TiiError = &tii.InvalidJSONError{}
var _ tii.TiiError = &tii.UnknownTxError{}
var _ tii.TiiError = &tii.UnknownProfileError{}
var _ tii.TiiError = &tii.InvalidParamsSchemaError{}
var _ tii.TiiError = &tii.InvalidParamTypeError{}
}

// TestTrpErrorMarker verifies TRP errors implement TrpError interface.
Expand Down
119 changes: 119 additions & 0 deletions sdk/testdata/complex.tii
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"tii": {
"version": "v1beta0"
},
"protocol": {
"name": "complex-types",
"scope": "unknown",
"version": "0.0.1",
"description": "Schema-only fixture exercising every ParamType kind. The TIR envelope is a non-resolvable placeholder; this vector is for parameter-type interpretation tests, not TRP resolution."
},
"environment": {
"type": "object",
"properties": {
"fee": {
"type": "integer"
}
},
"required": ["fee"]
},
"parties": {
"sender": {},
"receiver": {}
},
"profiles": {
"local": {
"environment": {},
"parties": {}
}
},
"components": {
"schemas": {
"AssetClass": {
"type": "object",
"properties": {
"policy": { "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/Bytes" },
"name": { "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/Bytes" }
},
"required": ["policy", "name"]
},
"Side": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": ["Buy"],
"properties": {
"Buy": { "type": "object", "properties": {}, "required": [] }
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["Sell"],
"properties": {
"Sell": {
"type": "object",
"properties": { "price": { "type": "integer" } },
"required": ["price"]
}
}
}
]
}
}
},
"transactions": {
"complex": {
"params": {
"type": "object",
"properties": {
"quantity": { "type": "integer" },
"flag": { "type": "boolean" },
"nothing": { "type": "null" },
"recipient": { "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/Address" },
"source": { "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/UtxoRef" },
"bag": { "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/AnyAsset" },
"amounts": {
"type": "array",
"items": { "type": "integer" }
},
"pair": {
"type": "array",
"prefixItems": [
{ "type": "integer" },
{ "$ref": "https://tx3.land/specs/v1beta0/tii#/$defs/Bytes" }
],
"items": false,
"minItems": 2,
"maxItems": 2
},
"labels": {
"type": "object",
"additionalProperties": { "type": "integer" }
},
"asset": { "$ref": "#/components/schemas/AssetClass" },
"side": { "$ref": "#/components/schemas/Side" }
},
"required": [
"quantity",
"flag",
"nothing",
"recipient",
"source",
"bag",
"amounts",
"pair",
"labels",
"asset",
"side"
]
},
"tir": {
"content": "00",
"encoding": "hex",
"version": "v1beta0"
}
}
}
}
20 changes: 0 additions & 20 deletions sdk/tii/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,3 @@ func (e *UnknownProfileError) Error() string {
return fmt.Sprintf("unknown profile: %q", e.Name)
}
func (e *UnknownProfileError) isTiiError() {}

// InvalidParamsSchemaError indicates the transaction's params schema is malformed.
type InvalidParamsSchemaError struct {
Detail string
}

func (e *InvalidParamsSchemaError) Error() string {
return fmt.Sprintf("invalid params schema: %s", e.Detail)
}
func (e *InvalidParamsSchemaError) isTiiError() {}

// InvalidParamTypeError indicates an unrecognized parameter type in the schema.
type InvalidParamTypeError struct {
Detail string
}

func (e *InvalidParamTypeError) Error() string {
return fmt.Sprintf("invalid param type: %s", e.Detail)
}
func (e *InvalidParamTypeError) isTiiError() {}
Loading
Loading