github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/pkg/stafidecoder/typeRegistry.go (about)

     1  package stafi_decoder
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"regexp"
     8  	"strings"
     9  
    10  	"github.com/itering/scale.go/utiles"
    11  )
    12  
    13  type RuntimeType struct{}
    14  
    15  type Special struct {
    16  	Version  []int
    17  	Registry interface{}
    18  }
    19  
    20  var TypeRegistry map[string]interface{}
    21  
    22  var specialRegistry map[string][]Special
    23  
    24  func (r RuntimeType) Reg() *RuntimeType {
    25  	registry := make(map[string]interface{})
    26  	scales := []interface{}{
    27  		&Null{},
    28  		&U8{},
    29  		&U16{},
    30  		&U32{},
    31  		&U64{},
    32  		&U128{},
    33  		&Compact{},
    34  		&H160{},
    35  		&H256{},
    36  		&H512{},
    37  		&Address{},
    38  		&Option{},
    39  		&Struct{},
    40  		&Enum{},
    41  		&Bytes{},
    42  		&Vec{},
    43  		&Set{},
    44  		&CompactU32{},
    45  		&Bool{},
    46  		&StorageHasher{},
    47  		&HexBytes{},
    48  		&Moment{},
    49  		&BlockNumber{},
    50  		&AccountId{},
    51  		&BoxProposal{},
    52  		&Signature{},
    53  		&Era{},
    54  		&EraExtrinsic{},
    55  		&Balance{},
    56  		&Index{},
    57  		&SessionIndex{},
    58  		&EraIndex{},
    59  		&ParaId{},
    60  		&LogDigest{},
    61  		&Other{},
    62  		&ChangesTrieRoot{},
    63  		&AuthoritiesChange{},
    64  		&SealV0{},
    65  		&Consensus{},
    66  		&Seal{},
    67  		&PreRuntime{},
    68  		&Exposure{},
    69  		&RawAuraPreDigest{},
    70  		&RawBabePreDigest{},
    71  		&RawBabePreDigestPrimary{},
    72  		&RawBabePreDigestSecondary{},
    73  		&RawBabePreDigestSecondaryVRF{},
    74  		&SlotNumber{},
    75  		&AccountIndex{},
    76  		&LockIdentifier{},
    77  		&BabeBlockWeight{},
    78  		&AuthorityId{},
    79  		&Call{},
    80  		&ReferendumIndex{},
    81  		&EcdsaSignature{},
    82  		&EthereumAddress{},
    83  		&PropIndex{},
    84  		&Data{},
    85  		&Vote{},
    86  		&VoteOutcome{},
    87  		&RawBabeLabel{},
    88  		&Key{},
    89  		&String{},
    90  		&GenericAddress{},
    91  		&OpaqueCall{},
    92  		&BitVec{},
    93  		&MetadataModuleEvent{},
    94  		&MetadataModuleCallArgument{},
    95  		&MetadataModuleCall{},
    96  		&MetadataV6Decoder{},
    97  		&MetadataV6Module{},
    98  		&MetadataV6ModuleStorage{},
    99  		&MetadataV6ModuleConstants{},
   100  		&MetadataV7Decoder{},
   101  		&MetadataV7Module{},
   102  		&MetadataV7ModuleStorage{},
   103  		&MetadataV7ModuleConstants{},
   104  		&MetadataV7ModuleStorageEntry{},
   105  		&MetadataV8Module{},
   106  		&MetadataV8Decoder{},
   107  		&MetadataV9Decoder{},
   108  		&MetadataV10Decoder{},
   109  		&MetadataV11Decoder{},
   110  		&MetadataV12Decoder{},
   111  		&MetadataV12Module{},
   112  		&MetadataModuleError{},
   113  		&GenericLookupSource{},
   114  		&BTreeMap{},
   115  	}
   116  	for _, class := range scales {
   117  		valueOf := reflect.ValueOf(class)
   118  		if valueOf.Type().Kind() == reflect.Ptr {
   119  			registry[strings.ToLower(reflect.Indirect(valueOf).Type().Name())] = class
   120  		} else {
   121  			registry[strings.ToLower(valueOf.Type().Name())] = class
   122  		}
   123  	}
   124  	registry["compact<u32>"] = &CompactU32{}
   125  	registry["compact<moment>"] = &Moment{}
   126  	registry["hash"] = &H256{}
   127  	registry["i8"] = &IntFixed{FixedLength: 1}
   128  	registry["i16"] = &IntFixed{FixedLength: 2}
   129  	registry["i32"] = &IntFixed{FixedLength: 4}
   130  	registry["i64"] = &IntFixed{FixedLength: 8}
   131  	registry["i128"] = &IntFixed{FixedLength: 16}
   132  	registry["[u8; 32]"] = &VecU8FixedLength{FixedLength: 32}
   133  	registry["[u8; 64]"] = &VecU8FixedLength{FixedLength: 64}
   134  	registry["[u8; 65]"] = &VecU8FixedLength{FixedLength: 65}
   135  	registry["[u8; 16]"] = &VecU8FixedLength{FixedLength: 16}
   136  	registry["[u8; 20]"] = &VecU8FixedLength{FixedLength: 20}
   137  	registry["[u8; 8]"] = &VecU8FixedLength{FixedLength: 8}
   138  	registry["[u8; 4]"] = &VecU8FixedLength{FixedLength: 4}
   139  	registry["[u8; 2]"] = &VecU8FixedLength{FixedLength: 2}
   140  	registry["[u8; 256]"] = &VecU8FixedLength{FixedLength: 256}
   141  	registry["[u128; 3]"] = &FixedLengthArray{FixedLength: 3, SubType: "u128"}
   142  	TypeRegistry = registry
   143  
   144  	RegCustomTypes(LoadTypeRegistry([]byte(BaseType)))
   145  	return &r
   146  }
   147  
   148  func (r *RuntimeType) getCodecInstant(t string, spec int) (reflect.Type, reflect.Value, error) {
   149  	t = strings.ToLower(t)
   150  	rt, err := r.specialVersionCodec(t, spec)
   151  
   152  	if err != nil {
   153  		rt = TypeRegistry[strings.ToLower(t)]
   154  		if rt == nil && t != "[]" && string(t[0]) == "[" && string(t[len(t)-1:]) == "]" {
   155  			if typePart := strings.Split(string(t[1:len(t)-1]), ";"); len(typePart) == 2 {
   156  				fixed := FixedLengthArray{
   157  					FixedLength: utiles.StringToInt(strings.TrimSpace(typePart[1])),
   158  					SubType:     strings.TrimSpace(typePart[0]),
   159  				}
   160  				rt = &fixed
   161  			}
   162  		}
   163  		if rt == nil {
   164  			return nil, reflect.ValueOf((*error)(nil)).Elem(), errors.New("Scale codec type nil" + t)
   165  		}
   166  	}
   167  
   168  	value := reflect.ValueOf(rt)
   169  	if value.Kind() == reflect.Ptr {
   170  		value = reflect.Indirect(value)
   171  	}
   172  	p := reflect.New(value.Type())
   173  	p.Elem().Set(value)
   174  	return p.Type(), p, nil
   175  }
   176  
   177  func (r *RuntimeType) DecoderClass(typeString string, spec int) (reflect.Type, reflect.Value, string) {
   178  	var typeParts []string
   179  	typeString = ConvertType(typeString, true)
   180  
   181  	if typeString[len(typeString)-1:] == ">" {
   182  		decoderClass, rc, err := r.getCodecInstant(typeString, spec)
   183  		if err == nil {
   184  			return decoderClass, rc, ""
   185  		}
   186  		reg := regexp.MustCompile("^([^<]*)<(.+)>$")
   187  		typeParts = reg.FindStringSubmatch(typeString)
   188  	}
   189  
   190  	if len(typeParts) > 0 {
   191  		class, rc, err := r.getCodecInstant(typeParts[1], spec)
   192  		if err == nil {
   193  			return class, rc, typeParts[2]
   194  		}
   195  	} else {
   196  		class, rc, err := r.getCodecInstant(typeString, spec)
   197  		if err == nil {
   198  			return class, rc, ""
   199  		}
   200  	}
   201  
   202  	if typeString != "()" && string(typeString[0]) == "(" && typeString[len(typeString)-1:] == ")" {
   203  		decoderClass, rc, _ := r.getCodecInstant("Struct", spec)
   204  		s := rc.Interface().(*Struct)
   205  		s.TypeString = typeString
   206  		s.buildStruct()
   207  		return decoderClass, rc, ""
   208  	}
   209  	return nil, reflect.ValueOf((*error)(nil)).Elem(), ""
   210  }
   211  
   212  func (r *RuntimeType) specialVersionCodec(t string, spec int) (interface{}, error) {
   213  	var rt interface{}
   214  
   215  	if specials, ok := specialRegistry[t]; ok {
   216  		for _, special := range specials {
   217  			if spec >= special.Version[0] && spec <= special.Version[1] {
   218  				rt = special.Registry
   219  				return rt, nil
   220  			}
   221  		}
   222  	}
   223  	return rt, fmt.Errorf("not found")
   224  }