diff --git a/models/common.go b/models/common.go index d456e4c..0480e3a 100644 --- a/models/common.go +++ b/models/common.go @@ -10,7 +10,7 @@ type SuiAddress string type SuiAddressBytes [32]byte type TransactionDigest string type ObjectDigest string -type ObjectDigestBytes [32]byte +type ObjectDigestBytes []byte func init() { var suiAddressBytes SuiAddressBytes @@ -29,6 +29,10 @@ func (s SuiAddressBytes) IsEqual(other SuiAddressBytes) bool { } func (o ObjectDigestBytes) IsEqual(other ObjectDigestBytes) bool { + if len(o) != len(other) { + return false + } + for i, b := range o { if b != other[i] { return false diff --git a/mystenbcs/decode.go b/mystenbcs/decode.go index 9d00b78..b598035 100644 --- a/mystenbcs/decode.go +++ b/mystenbcs/decode.go @@ -70,7 +70,7 @@ func (d *Decoder) decode(v reflect.Value) (int, error) { switch v.Kind() { case reflect.Pointer, reflect.Interface: if v.IsNil() { - return 0, fmt.Errorf("trying to decode into nil pointer/interface") + v.Set(reflect.New(v.Type().Elem())) } return d.decodeEnum(v.Elem()) default: @@ -143,6 +143,10 @@ func (d *Decoder) decodeVanilla(v reflect.Value) (int, error) { return d.decodeSlice(v) case reflect.Array: + arrayType := v.Type().Elem() + if arrayType.Kind() == reflect.Uint8 { + return d.decodeByteArray(v) + } return d.decodeArray(v) case reflect.String: @@ -222,7 +226,7 @@ fieldLoop: return n, err } if isOptional == 0 { - field.Set(reflect.Zero(v.Type())) + field.Set(reflect.Zero(field.Type())) } else { field.Set(reflect.New(field.Type().Elem())) k, err := d.decode(field.Elem()) @@ -287,6 +291,31 @@ func (d *Decoder) decodeByteSlice(v reflect.Value) (int, error) { return n, nil } +func (d *Decoder) decodeByteArray(v reflect.Value) (int, error) { + arraySize := v.Len() + + if arraySize == 0 { + return 0, nil + } + + tmp := make([]byte, arraySize) + + read, err := d.reader.Read(tmp) + if err != nil { + return read, err + } + + if arraySize != read { + return read, fmt.Errorf("wrong number of bytes read for [%d]byte, want: %d, got %d", arraySize, arraySize, read) + } + + for i := 0; i < arraySize; i++ { + v.Index(i).SetUint(uint64(tmp[i])) + } + + return read, nil +} + func (d *Decoder) decodeArray(v reflect.Value) (int, error) { size := v.Len() t := v.Type() @@ -333,7 +362,7 @@ func (d *Decoder) decodeSlice(v reflect.Value) (int, error) { if elementType.Kind() == reflect.Pointer { for i := 0; i < size; i++ { ind := reflect.New(elementType.Elem()) - k, err := d.decode(ind.Elem()) + k, err := d.decode(ind) n += k if err != nil { return n, err diff --git a/transaction/convert.go b/transaction/convert.go index 2b17033..2029661 100644 --- a/transaction/convert.go +++ b/transaction/convert.go @@ -37,12 +37,9 @@ func ConvertObjectDigestStringToBytes(digest models.ObjectDigest) (*models.Objec return nil, ErrInvalidObjectId } - var fixedBytes [32]byte - copy(fixedBytes[:], decoded) - - return (*models.ObjectDigestBytes)(&fixedBytes), nil + return (*models.ObjectDigestBytes)(&decoded), nil } func ConvertObjectDigestBytesToString(digest models.ObjectDigestBytes) models.ObjectDigest { - return models.ObjectDigest(base58.Encode(digest[:])) + return models.ObjectDigest(base58.Encode(digest)) } diff --git a/transaction/transaction_data_test.go b/transaction/transaction_data_test.go new file mode 100644 index 0000000..cfc19d1 --- /dev/null +++ b/transaction/transaction_data_test.go @@ -0,0 +1,23 @@ +package transaction + +import ( + "encoding/base64" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/block-vision/sui-go-sdk/mystenbcs" +) + +func TestBcsUnmarshal(t *testing.T) { + b64Tx := "AAAIAQBiBnaLHr5TzVJu29SyLYueU6dFUyLeaY9ZeK11c+8IrXPUayEAAAAAIP3zvI2RTxZdaMnH47J4OJQbyHdIb50BtZ2JxNb4gD7AAQDo6vegaubVlLDf0hxZfOtmAkBc4ryrHxXfLLjFo72CF4bUayEAAAAAIECXRV/tLtwVmiAi/xXB6L5v1KFuEZQ0oah1NwYdBcLfAAgAhNcXAAAAAAEB2qRikmMsPE2PMfI+oPmzaij/NnfpaEmA5EOEA6Z6PY8uBRgAAAAAAAABAa2qRWjdYdo2MMQNLRRttp5jmUbSJZnqQxXT0+oBmR8aY8ddIQAAAAABAQFjm15DPaMXOegAzQhfNW5kyuIilm0PGxG9ncdrMi/1i2LvCxMAAAAAAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAAAAAAAAAACE7aKJKcAwAABwMBAAABAQEAAgEAAAEBAgACAwEAAAABAQIAADhkx8WaSIn+wF0arkvJ26Wg4JQFlLQk++1Eyz9qxMAyBWNldHVzCHN3YXBfYjJhAgfhtFoOZBuZVaIKoK0cH0rYaq2K+wcpbUCF40mlDpC9ygRibHVlBEJMVUUAB9ujRnLjDLBlsfk+OrVTGHaP1v72bBWULJ98uEbi+QDnBHVzZGMEVVNEQwAFAQMAAQQAAQUAAwIAAAABBgAAJIX+udQsfDvLjs3lVa1A8bBz2ftPrzVPotMKCxg6I84FdXRpbHMYdHJhbnNmZXJfb3JfZGVzdHJveV9jb2luAQfbo0Zy4wywZbH5Pjq1Uxh2j9b+9mwVlCyffLhG4vkA5wR1c2RjBFVTREMAAQMBAAAAACSF/rnULHw7y47N5VWtQPGwc9n7T681T6LTCgsYOiPOBXV0aWxzFGNoZWNrX2NvaW5fdGhyZXNob2xkAQfhtFoOZBuZVaIKoK0cH0rYaq2K+wcpbUCF40mlDpC9ygRibHVlBEJMVUUAAgMDAAAAAQcAACSF/rnULHw7y47N5VWtQPGwc9n7T681T6LTCgsYOiPOBXV0aWxzGHRyYW5zZmVyX29yX2Rlc3Ryb3lfY29pbgEH4bRaDmQbmVWiCqCtHB9K2GqtivsHKW1AheNJpQ6QvcoEYmx1ZQRCTFVFAAEDAwAAAPGLdfcB6yxirRUeIzQYdrBeeCZsC49tvfE1MjQ3HRe+AeFyymxHLoC1zuCDjWceFIVGpQinWoTY3E/nQtJ0PXeLhtRrIQAAAAAg7wnlIFKxbd6S0eZ7pktb3VGeUCezpe3rCIK/6e1qR+7xi3X3AessYq0VHiM0GHawXngmbAuPbb3xNTI0Nx0Xvu4CAAAAAAAAAOH1BQAAAAAA" + txBz, _ := base64.StdEncoding.DecodeString(b64Tx) + + var txData TransactionData + _, err := mystenbcs.Unmarshal(txBz, &txData) + require.NoError(t, err) + + genBz, err := txData.Marshal() + require.NoError(t, err) + require.Equal(t, txBz, genBz) +}