From b90c0ece87970f09382efc9b2f0c81e13ed7cf1d Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 23 Jan 2024 14:47:07 +0300 Subject: [PATCH] smartcontract: introduce Convertible interface Allow to pass Convertible to NewParameterFromValue. Close #3285. Signed-off-by: Anna Shaleva --- pkg/smartcontract/parameter.go | 11 ++++++ pkg/smartcontract/parameter_test.go | 55 +++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index 758b86bd1..24577d854 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -25,6 +25,11 @@ type Parameter struct { Value any `json:"value"` } +// Convertible is something that can be converted to Parameter. +type Convertible interface { + ToSCParameter() (Parameter, error) +} + // ParameterPair represents a key-value pair, a slice of which is stored in // MapType Parameter. type ParameterPair struct { @@ -307,6 +312,12 @@ func NewParameterFromValue(value any) (Parameter, error) { result = *v case Parameter: result = v + case Convertible: + var err error + result, err = v.ToSCParameter() + if err != nil { + return result, fmt.Errorf("failed to convert smartcontract.Convertible (%T) to Parameter: %w", v, err) + } case util.Uint160: result.Type = Hash160Type case util.Uint256: diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index c93179a2a..a4353a50f 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" + "errors" "math" "math/big" "strings" @@ -554,6 +555,25 @@ func TestExpandParameterToEmitableToStackitem(t *testing.T) { } } +// testConvertible implements Convertible interface and needed for NewParameterFromValue +// test. +type testConvertible struct { + i int + err string +} + +var _ = Convertible(testConvertible{}) + +func (c testConvertible) ToSCParameter() (Parameter, error) { + if c.err != "" { + return Parameter{}, errors.New(c.err) + } + return Parameter{ + Type: IntegerType, + Value: c.i, + }, nil +} + func TestParameterFromValue(t *testing.T) { pk1, _ := keys.NewPrivateKey() pk2, _ := keys.NewPrivateKey() @@ -561,6 +581,7 @@ func TestParameterFromValue(t *testing.T) { value any expType ParamType expVal any + err string // expected error substring }{ { value: []byte{1, 2, 3}, @@ -741,14 +762,42 @@ func TestParameterFromValue(t *testing.T) { Value: []byte{1, 2, 3}, }}, }, + { + value: testConvertible{i: 123}, + expType: IntegerType, + expVal: 123, + }, + { + value: []any{1, testConvertible{i: 123}}, + expType: ArrayType, + expVal: []Parameter{ + { + Type: IntegerType, + Value: big.NewInt(1), + }, + { + Type: IntegerType, + Value: 123, + }, + }, + }, + { + value: testConvertible{err: "invalid i value"}, + err: "invalid i value", + }, } for _, item := range items { t.Run(item.expType.String()+" to stack parameter", func(t *testing.T) { res, err := NewParameterFromValue(item.value) - require.NoError(t, err) - require.Equal(t, item.expType, res.Type) - require.Equal(t, item.expVal, res.Value) + if item.err != "" { + require.Error(t, err) + require.Contains(t, err.Error(), item.err) + } else { + require.NoError(t, err) + require.Equal(t, item.expType, res.Type) + require.Equal(t, item.expVal, res.Value) + } }) } _, err := NewParameterFromValue(make(map[string]int))