Skip to content

Commit

Permalink
Add metadata V12
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurentTrk committed Oct 5, 2020
1 parent e823330 commit 94e87b9
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 0 deletions.
23 changes: 23 additions & 0 deletions types/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type Metadata struct {
AsMetadataV10 MetadataV10
IsMetadataV11 bool
AsMetadataV11 MetadataV11
IsMetadataV12 bool
AsMetadataV12 MetadataV12
}

func NewMetadataV4() *Metadata {
Expand Down Expand Up @@ -71,6 +73,14 @@ func NewMetadataV11() *Metadata {
}
}

func NewMetadataV12() *Metadata {
return &Metadata{
Version: 12,
IsMetadataV12: true,
AsMetadataV12: MetadataV12{Modules: make([]ModuleMetadataV12, 0)},
}
}

func (m *Metadata) Decode(decoder scale.Decoder) error {
err := decoder.Decode(&m.MagicNumber)
if err != nil {
Expand Down Expand Up @@ -104,6 +114,9 @@ func (m *Metadata) Decode(decoder scale.Decoder) error {
case 11:
m.IsMetadataV11 = true
err = decoder.Decode(&m.AsMetadataV11)
case 12:
m.IsMetadataV12 = true
err = decoder.Decode(&m.AsMetadataV12)
default:
return fmt.Errorf("unsupported metadata version %v", m.Version)
}
Expand Down Expand Up @@ -135,6 +148,8 @@ func (m Metadata) Encode(encoder scale.Encoder) error {
err = encoder.Encode(m.AsMetadataV10)
case 11:
err = encoder.Encode(m.AsMetadataV11)
case 12:
err = encoder.Encode(m.AsMetadataV12)
default:
return fmt.Errorf("unsupported metadata version %v", m.Version)
}
Expand All @@ -156,6 +171,8 @@ func (m *Metadata) FindCallIndex(call string) (CallIndex, error) {
return m.AsMetadataV10.FindCallIndex(call)
case m.IsMetadataV11:
return m.AsMetadataV11.FindCallIndex(call)
case m.IsMetadataV12:
return m.AsMetadataV12.FindCallIndex(call)
default:
return CallIndex{}, fmt.Errorf("unsupported metadata version")
}
Expand All @@ -175,6 +192,8 @@ func (m *Metadata) FindEventNamesForEventID(eventID EventID) (Text, Text, error)
return m.AsMetadataV10.FindEventNamesForEventID(eventID)
case m.IsMetadataV11:
return m.AsMetadataV11.FindEventNamesForEventID(eventID)
case m.IsMetadataV12:
return m.AsMetadataV12.FindEventNamesForEventID(eventID)
default:
return "", "", fmt.Errorf("unsupported metadata version")
}
Expand All @@ -194,6 +213,8 @@ func (m *Metadata) FindStorageEntryMetadata(module string, fn string) (StorageEn
return m.AsMetadataV10.FindStorageEntryMetadata(module, fn)
case m.IsMetadataV11:
return m.AsMetadataV11.FindStorageEntryMetadata(module, fn)
case m.IsMetadataV12:
return m.AsMetadataV12.FindStorageEntryMetadata(module, fn)
default:
return nil, fmt.Errorf("unsupported metadata version")
}
Expand All @@ -213,6 +234,8 @@ func (m *Metadata) ExistsModuleMetadata(module string) bool {
return m.AsMetadataV10.ExistsModuleMetadata(module)
case m.IsMetadataV11:
return m.AsMetadataV11.ExistsModuleMetadata(module)
case m.IsMetadataV12:
return m.AsMetadataV12.ExistsModuleMetadata(module)
default:
return false
}
Expand Down
217 changes: 217 additions & 0 deletions types/metadataV12.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package types

import (
"fmt"
"github.com/centrifuge/go-substrate-rpc-client/scale"
"strings"
)

// Modelled after packages/types/src/Metadata/v11/toV12.ts
type MetadataV12 struct {
Modules []ModuleMetadataV12
Extrinsic ExtrinsicV11
}

func (m *MetadataV12) Decode(decoder scale.Decoder) error {
err := decoder.Decode(&m.Modules)
if err != nil {
return err
}
return decoder.Decode(&m.Extrinsic)
}

func (m MetadataV12) Encode(encoder scale.Encoder) error {
err := encoder.Encode(m.Modules)
if err != nil {
return err
}
return encoder.Encode(m.Extrinsic)
}

func (m *MetadataV12) FindCallIndex(call string) (CallIndex, error) {
s := strings.Split(call, ".")
mi := uint8(0)
for _, mod := range m.Modules {
if !mod.HasCalls {
continue
}
if string(mod.Name) != s[0] {
mi++
continue
}
for ci, f := range mod.Calls {
if string(f.Name) == s[1] {
return CallIndex{mi, uint8(ci)}, nil
}
}
return CallIndex{}, fmt.Errorf("method %v not found within module %v for call %v", s[1], mod.Name, call)
}
return CallIndex{}, fmt.Errorf("module %v not found in metadata for call %v", s[0], call)
}

func (m *MetadataV12) FindEventNamesForEventID(eventID EventID) (Text, Text, error) {
for _, mod := range m.Modules {
if !mod.HasEvents {
continue
}
if mod.Index != eventID[0] {
continue
}
if int(eventID[1]) >= len(mod.Events) {
return "", "", fmt.Errorf("event index %v for module %v out of range", eventID[1], mod.Name)
}
return mod.Name, mod.Events[eventID[1]].Name, nil
}
return "", "", fmt.Errorf("module index %v out of range", eventID[0])
}

func (m *MetadataV12) FindStorageEntryMetadata(module string, fn string) (StorageEntryMetadata, error) {
for _, mod := range m.Modules {
if !mod.HasStorage {
continue
}
if string(mod.Storage.Prefix) != module {
continue
}
for _, s := range mod.Storage.Items {
if string(s.Name) != fn {
continue
}
return s, nil
}
return nil, fmt.Errorf("storage %v not found within module %v", fn, module)
}
return nil, fmt.Errorf("module %v not found in metadata", module)
}

func (m *MetadataV12) ExistsModuleMetadata(module string) bool {
for _, mod := range m.Modules {
if string(mod.Name) == module {
return true
}
}
return false
}

type ModuleMetadataV12 struct {
Name Text
HasStorage bool
Storage StorageMetadataV10
HasCalls bool
Calls []FunctionMetadataV4
HasEvents bool
Events []EventMetadataV4
Constants []ModuleConstantMetadataV6
Errors []ErrorMetadataV8
Index uint8
}

func (m *ModuleMetadataV12) Decode(decoder scale.Decoder) error {
err := decoder.Decode(&m.Name)
if err != nil {
return err
}

err = decoder.Decode(&m.HasStorage)
if err != nil {
return err
}

if m.HasStorage {
err = decoder.Decode(&m.Storage)
if err != nil {
return err
}
}

err = decoder.Decode(&m.HasCalls)
if err != nil {
return err
}

if m.HasCalls {
err = decoder.Decode(&m.Calls)
if err != nil {
return err
}
}

err = decoder.Decode(&m.HasEvents)
if err != nil {
return err
}

if m.HasEvents {
err = decoder.Decode(&m.Events)
if err != nil {
return err
}
}

err = decoder.Decode(&m.Constants)
if err != nil {
return err
}

err = decoder.Decode(&m.Errors)
if err != nil {
return err
}

return decoder.Decode(&m.Index)
}

func (m ModuleMetadataV12) Encode(encoder scale.Encoder) error {
err := encoder.Encode(m.Name)
if err != nil {
return err
}

err = encoder.Encode(m.HasStorage)
if err != nil {
return err
}

if m.HasStorage {
err = encoder.Encode(m.Storage)
if err != nil {
return err
}
}

err = encoder.Encode(m.HasCalls)
if err != nil {
return err
}

if m.HasCalls {
err = encoder.Encode(m.Calls)
if err != nil {
return err
}
}

err = encoder.Encode(m.HasEvents)
if err != nil {
return err
}

if m.HasEvents {
err = encoder.Encode(m.Events)
if err != nil {
return err
}
}

err = encoder.Encode(m.Constants)
if err != nil {
return err
}

err = encoder.Encode(m.Errors)
if err != nil {
return err
}

return encoder.Encode(m.Index)
}
20 changes: 20 additions & 0 deletions types/metadataV12_examplary_string.go

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions types/metadataV12_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package types_test

import (
"testing"

. "github.com/centrifuge/go-substrate-rpc-client/types"
"github.com/stretchr/testify/assert"
)

var exampleMetadataV12 = Metadata{
MagicNumber: 0x6174656d,
Version: 12,
IsMetadataV12: true,
AsMetadataV12: exampleRuntimeMetadataV12,
}

var exampleRuntimeMetadataV12 = MetadataV12{
Modules: []ModuleMetadataV12{exampleModuleMetadataV12Empty, exampleModuleMetadataV121, exampleModuleMetadataV122},
}

var exampleModuleMetadataV12Empty = ModuleMetadataV12{
Name: "EmptyModule",
HasStorage: false,
Storage: StorageMetadataV10{},
HasCalls: false,
Calls: nil,
HasEvents: false,
Events: nil,
Constants: nil,
Errors: nil,
Index: 0,
}

var exampleModuleMetadataV121 = ModuleMetadataV12{
Name: "Module1",
HasStorage: true,
Storage: exampleStorageMetadataV10,
HasCalls: true,
Calls: []FunctionMetadataV4{exampleFunctionMetadataV4},
HasEvents: true,
Events: []EventMetadataV4{exampleEventMetadataV4},
Constants: []ModuleConstantMetadataV6{exampleModuleConstantMetadataV6},
Errors: []ErrorMetadataV8{exampleErrorMetadataV8},
Index: 1,
}

var exampleModuleMetadataV122 = ModuleMetadataV12{
Name: "Module2",
HasStorage: true,
Storage: exampleStorageMetadataV10,
HasCalls: true,
Calls: []FunctionMetadataV4{exampleFunctionMetadataV4},
HasEvents: true,
Events: []EventMetadataV4{exampleEventMetadataV4},
Constants: []ModuleConstantMetadataV6{exampleModuleConstantMetadataV6},
Errors: []ErrorMetadataV8{exampleErrorMetadataV8},
Index: 2,
}

func TestNewMetadataV12_Decode(t *testing.T) {
tests := []struct {
name, hexData string
}{
{
"PolkadotV12", ExamplaryMetadataV12PolkadotString,
},
}

for _, s := range tests {
t.Run(s.name, func(t *testing.T) {
metadata := NewMetadataV12()
err := DecodeFromBytes(MustHexDecodeString(s.hexData), metadata)
assert.True(t, metadata.IsMetadataV12)
assert.NoError(t, err)
data, err := EncodeToBytes(metadata)
assert.NoError(t, err)
assert.Equal(t, s.hexData, HexEncodeToString(data))
})

}
}

func TestMetadataV12_ExistsModuleMetadata(t *testing.T) {
assert.True(t, exampleMetadataV12.ExistsModuleMetadata("EmptyModule"))
assert.False(t, exampleMetadataV12.ExistsModuleMetadata("NotExistModule"))
}

0 comments on commit 94e87b9

Please sign in to comment.