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

     1  package client
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/ethereum/go-ethereum/common/hexutil"
    11  	"github.com/gorilla/websocket"
    12  	scalecodec "github.com/itering/scale.go"
    13  	scaleTypes "github.com/itering/scale.go/types"
    14  	scaleBytes "github.com/itering/scale.go/types/scaleBytes"
    15  	"github.com/itering/scale.go/utiles"
    16  	"github.com/itering/substrate-api-rpc/rpc"
    17  	"github.com/stafiprotocol/go-substrate-rpc-client/config"
    18  	"github.com/stafiprotocol/go-substrate-rpc-client/pkg/stafidecoder"
    19  	gsrpc "github.com/stafiprotocol/go-substrate-rpc-client/rpc"
    20  	"github.com/stafiprotocol/go-substrate-rpc-client/types"
    21  	commonTypes "github.com/stafiprotocol/go-substrate-rpc-client/types/common"
    22  )
    23  
    24  func (sc *GsrpcClient) FlashApi() (*gsrpc.RPCS, error) {
    25  	_, err := sc.rpcs.Chain.GetBlockHashLatest()
    26  	if err != nil {
    27  		var rpcs *gsrpc.RPCS
    28  		for i := 0; i < 3; i++ {
    29  			rpcs, err = gsrpc.NewRPCS(sc.endpoint)
    30  			if err == nil {
    31  				break
    32  			} else {
    33  				time.Sleep(time.Millisecond * 100)
    34  			}
    35  		}
    36  		if rpcs != nil {
    37  			sc.rpcs = rpcs
    38  		}
    39  	}
    40  	return sc.rpcs, nil
    41  }
    42  
    43  func (sc *GsrpcClient) Address() string {
    44  	return sc.key.Address
    45  }
    46  
    47  func (sc *GsrpcClient) GetLatestBlockNumber() (uint64, error) {
    48  	h, err := sc.GetHeaderLatest()
    49  	if err != nil {
    50  		return 0, err
    51  	}
    52  
    53  	return uint64(h.Number), nil
    54  }
    55  
    56  func (sc *GsrpcClient) GetFinalizedBlockNumber() (uint64, error) {
    57  	hash, err := sc.GetFinalizedHead()
    58  	if err != nil {
    59  		return 0, err
    60  	}
    61  
    62  	header, err := sc.GetHeader(hash)
    63  	if err != nil {
    64  		return 0, err
    65  	}
    66  
    67  	return uint64(header.Number), nil
    68  }
    69  
    70  func (sc *GsrpcClient) GetHeaderLatest() (*types.Header, error) {
    71  	api, err := sc.FlashApi()
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	return api.Chain.GetHeaderLatest()
    76  }
    77  
    78  func (sc *GsrpcClient) GetFinalizedHead() (types.Hash, error) {
    79  	api, err := sc.FlashApi()
    80  	if err != nil {
    81  		return types.NewHash([]byte{}), err
    82  	}
    83  	return api.Chain.GetFinalizedHead()
    84  }
    85  
    86  func (sc *GsrpcClient) GetHeader(blockHash types.Hash) (*types.Header, error) {
    87  	api, err := sc.FlashApi()
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	return api.Chain.GetHeader(blockHash)
    92  }
    93  
    94  func (sc *GsrpcClient) GetBlockNumber(blockHash types.Hash) (uint64, error) {
    95  	head, err := sc.GetHeader(blockHash)
    96  	if err != nil {
    97  		return 0, err
    98  	}
    99  
   100  	return uint64(head.Number), nil
   101  }
   102  
   103  // queryStorage performs a storage lookup. Arguments may be nil, result must be a pointer.
   104  func (sc *GsrpcClient) QueryStorage(prefix, method string, arg1, arg2 []byte, result interface{}) (bool, error) {
   105  	entry, err := sc.FindStorageEntryMetadata(prefix, method)
   106  	if err != nil {
   107  		return false, err
   108  	}
   109  
   110  	var key types.StorageKey
   111  	keySeted := false
   112  	if entry.IsNMap() {
   113  		hashers, err := entry.Hashers()
   114  		if err != nil {
   115  			return false, err
   116  		}
   117  
   118  		if len(hashers) == 1 {
   119  			key, err = types.CreateStorageKeyWithEntryMeta(uint8(sc.metaDataVersion), entry, prefix, method, arg1)
   120  			if err != nil {
   121  				return false, err
   122  			}
   123  			keySeted = true
   124  		}
   125  	}
   126  
   127  	if !keySeted {
   128  		key, err = types.CreateStorageKeyWithEntryMeta(uint8(sc.metaDataVersion), entry, prefix, method, arg1, arg2)
   129  		if err != nil {
   130  			return false, err
   131  		}
   132  	}
   133  
   134  	api, err := sc.FlashApi()
   135  	if err != nil {
   136  		return false, err
   137  	}
   138  	sc.log.Trace("QueryStorage", "entry.IsNMap", entry.IsNMap(), "metaDataVersion", sc.metaDataVersion, "prefix", prefix, "method", method, "arg1", arg1, "arg2", arg2, "storageKey", hexutil.Encode(key))
   139  
   140  	ok, err := api.State.GetStorageLatest(key, result)
   141  	if err != nil {
   142  		return false, err
   143  	}
   144  
   145  	return ok, nil
   146  }
   147  
   148  func (sc *GsrpcClient) GetLatestRuntimeVersion() (*types.RuntimeVersion, error) {
   149  	api, err := sc.FlashApi()
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	rv, err := api.State.GetRuntimeVersionLatest()
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	return rv, nil
   159  }
   160  
   161  func (sc *GsrpcClient) GetLatestNonce() (types.U32, error) {
   162  	ac, err := sc.GetAccountInfo()
   163  	if err != nil {
   164  		return 0, err
   165  	}
   166  
   167  	return ac.Nonce, nil
   168  }
   169  
   170  func (sc *GsrpcClient) GetAccountInfo() (*types.AccountInfo, error) {
   171  	ac := new(types.AccountInfo)
   172  	exist, err := sc.QueryStorage("System", "Account", sc.key.PublicKey, nil, &ac)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	if !exist {
   178  		return nil, errors.New("account not exist")
   179  	}
   180  
   181  	return ac, nil
   182  }
   183  
   184  func (sc *GsrpcClient) PublicKey() []byte {
   185  	return sc.key.PublicKey
   186  }
   187  
   188  func (sc *GsrpcClient) StakingLedger(ac types.AccountID) (*StakingLedger, error) {
   189  	s := new(StakingLedger)
   190  	exist, err := sc.QueryStorage(config.StakingModuleId, config.StorageLedger, ac[:], nil, s)
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  
   195  	if !exist {
   196  		return nil, fmt.Errorf("can not get active for account: %s", hexutil.Encode(ac[:]))
   197  	}
   198  
   199  	return s, nil
   200  }
   201  
   202  func (sc *GsrpcClient) FreeBalance(who []byte) (types.U128, error) {
   203  	if sc.addressType == AddressTypeMultiAddress {
   204  		info, err := sc.NewVersionAccountInfo(who)
   205  		if err != nil {
   206  			return types.U128{}, err
   207  		}
   208  		return info.Data.Free, nil
   209  	}
   210  
   211  	info, err := sc.AccountInfo(who)
   212  	if err != nil {
   213  		return types.U128{}, err
   214  	}
   215  
   216  	return info.Data.Free, nil
   217  }
   218  
   219  func (sc *GsrpcClient) AccountInfo(who []byte) (*types.AccountInfo, error) {
   220  	ac := new(types.AccountInfo)
   221  	exist, err := sc.QueryStorage(config.SystemModuleId, config.StorageAccount, who, nil, ac)
   222  	if err != nil {
   223  		return nil, err
   224  	}
   225  
   226  	if !exist {
   227  		return nil, fmt.Errorf("can not get accountInfo for account: %s", hexutil.Encode(who))
   228  	}
   229  
   230  	return ac, nil
   231  }
   232  
   233  func (sc *GsrpcClient) NewVersionAccountInfo(who []byte) (*AccountInfo, error) {
   234  	ac := new(AccountInfo)
   235  	exist, err := sc.QueryStorage(config.SystemModuleId, config.StorageAccount, who, nil, ac)
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  
   240  	if !exist {
   241  		return nil, fmt.Errorf("can not get accountInfo for account: %s", hexutil.Encode(who))
   242  	}
   243  	return ac, nil
   244  }
   245  
   246  func (sc *GsrpcClient) ExistentialDeposit() (types.U128, error) {
   247  	_, err := sc.FlashApi()
   248  	if err != nil {
   249  		return types.U128{}, err
   250  	}
   251  	var e types.U128
   252  	err = sc.GetConst(config.BalancesModuleId, config.ConstExistentialDeposit, &e)
   253  	if err != nil {
   254  		return types.U128{}, err
   255  	}
   256  	return e, nil
   257  }
   258  
   259  func (sc *GsrpcClient) GetConst(prefix, name string, res interface{}) error {
   260  
   261  	switch sc.chainType {
   262  	case ChainTypeStafi:
   263  		return sc.rpcs.State.GetConst(prefix, name, &res)
   264  	case ChainTypePolkadot:
   265  		blockHash, err := sc.GetFinalizedHead()
   266  		if err != nil {
   267  			return err
   268  		}
   269  		md, err := sc.getPolkaMetaDecoder(blockHash.Hex())
   270  		if err != nil {
   271  			return err
   272  		}
   273  
   274  		for _, mod := range md.Metadata.Metadata.Modules {
   275  			if string(mod.Prefix) == prefix {
   276  				for _, cons := range mod.Constants {
   277  					if cons.Name == name {
   278  
   279  						return types.DecodeFromHexString(cons.ConstantsValue, res)
   280  					}
   281  				}
   282  			}
   283  		}
   284  		return fmt.Errorf("could not find constant %s.%s", prefix, name)
   285  	default:
   286  		return errors.New("GetConst chainType not supported")
   287  	}
   288  }
   289  
   290  func (sc *GsrpcClient) FindStorageEntryMetadata(module string, fn string) (types.StorageEntryMetadata, error) {
   291  	switch sc.chainType {
   292  	case ChainTypeStafi:
   293  		meta, err := sc.rpcs.State.GetMetadataLatest()
   294  		if err != nil {
   295  			return nil, err
   296  		}
   297  
   298  		return meta.FindStorageEntryMetadata(module, fn)
   299  	case ChainTypePolkadot:
   300  		blockHash, err := sc.GetFinalizedHead()
   301  		if err != nil {
   302  			return nil, err
   303  		}
   304  		md, err := sc.getPolkaMetaDecoder(blockHash.Hex())
   305  		if err != nil {
   306  			return nil, err
   307  		}
   308  
   309  		for _, mod := range md.Metadata.Metadata.Modules {
   310  			if string(mod.Prefix) != module {
   311  				continue
   312  			}
   313  			for _, s := range mod.Storage {
   314  				if string(s.Name) != fn {
   315  					continue
   316  				}
   317  
   318  				sfm := types.StorageFunctionMetadataV13{
   319  					Name: types.Text(s.Name),
   320  				}
   321  
   322  				if s.Type.PlainType != nil {
   323  					sfm.Type = types.StorageFunctionTypeV13{
   324  						IsType: true,
   325  						AsType: types.Type(*s.Type.PlainType),
   326  					}
   327  				}
   328  
   329  				if s.Type.DoubleMapType != nil {
   330  					dmt := types.DoubleMapTypeV10{
   331  						Key1:       types.Type(s.Type.DoubleMapType.Key),
   332  						Key2:       types.Type(s.Type.DoubleMapType.Key2),
   333  						Value:      types.Type(s.Type.DoubleMapType.Value),
   334  						Hasher:     TransformHasher(s.Type.DoubleMapType.Hasher),
   335  						Key2Hasher: TransformHasher(s.Type.DoubleMapType.Key2Hasher),
   336  					}
   337  
   338  					sfm.Type = types.StorageFunctionTypeV13{
   339  						IsDoubleMap: true,
   340  						AsDoubleMap: dmt,
   341  					}
   342  				}
   343  
   344  				if s.Type.MapType != nil {
   345  					mt := types.MapTypeV10{
   346  						Key:    types.Type(s.Type.MapType.Key),
   347  						Value:  types.Type(s.Type.MapType.Value),
   348  						Linked: s.Type.MapType.IsLinked,
   349  						Hasher: TransformHasher(s.Type.MapType.Hasher),
   350  					}
   351  
   352  					sfm.Type = types.StorageFunctionTypeV13{
   353  						IsMap: true,
   354  						AsMap: mt,
   355  					}
   356  				}
   357  
   358  				if s.Type.NMapType != nil {
   359  					keys := make([]types.Type, 0)
   360  					for _, key := range s.Type.NMapType.KeyVec {
   361  						keys = append(keys, types.Type(key))
   362  					}
   363  
   364  					hashers := make([]types.StorageHasherV10, 0)
   365  					for _, hasher := range s.Type.NMapType.Hashers {
   366  						hashers = append(hashers, TransformHasher(hasher))
   367  					}
   368  
   369  					nmt := types.NMapTypeV13{
   370  						Keys:    keys,
   371  						Hashers: hashers,
   372  						Value:   types.Type(s.Type.NMapType.Value),
   373  					}
   374  
   375  					sfm.Type = types.StorageFunctionTypeV13{
   376  						IsNMap: true,
   377  						AsNMap: nmt,
   378  					}
   379  				}
   380  
   381  				return sfm, nil
   382  			}
   383  			return nil, fmt.Errorf("storage %v not found within module %v", fn, module)
   384  		}
   385  		return nil, fmt.Errorf("module %v not found in metadata", module)
   386  	default:
   387  		return nil, errors.New("chainType not supported")
   388  	}
   389  }
   390  
   391  func (sc *GsrpcClient) FindCallIndex(call string) (types.CallIndex, error) {
   392  	switch sc.chainType {
   393  	case ChainTypeStafi:
   394  		meta, err := sc.rpcs.State.GetMetadataLatest()
   395  		if err != nil {
   396  			return types.CallIndex{}, err
   397  		}
   398  
   399  		return meta.FindCallIndex(call)
   400  	case ChainTypePolkadot:
   401  		blockHash, err := sc.GetFinalizedHead()
   402  		if err != nil {
   403  			return types.CallIndex{}, err
   404  		}
   405  
   406  		md, err := sc.getPolkaMetaDecoder(blockHash.Hex())
   407  		if err != nil {
   408  			return types.CallIndex{}, err
   409  		}
   410  		s := strings.Split(call, ".")
   411  
   412  		for _, mod := range md.Metadata.Metadata.Modules {
   413  			if string(mod.Name) != s[0] {
   414  				continue
   415  			}
   416  			for ci, f := range mod.Calls {
   417  				if string(f.Name) == s[1] {
   418  					return types.CallIndex{SectionIndex: uint8(mod.Index), MethodIndex: uint8(ci)}, nil
   419  				}
   420  			}
   421  			return types.CallIndex{}, fmt.Errorf("method %v not found within module %v for call %v", s[1], mod.Name, call)
   422  		}
   423  		return types.CallIndex{}, fmt.Errorf("module %v not found in metadata for call %v", s[0], call)
   424  
   425  	default:
   426  		return types.CallIndex{}, errors.New("FindCallIndex chainType not supported")
   427  	}
   428  }
   429  
   430  func TransformHasher(Hasher string) types.StorageHasherV10 {
   431  	if Hasher == "Blake2_128" {
   432  		return types.StorageHasherV10{IsBlake2_128: true}
   433  	}
   434  
   435  	if Hasher == "Blake2_256" {
   436  		return types.StorageHasherV10{IsBlake2_256: true}
   437  	}
   438  
   439  	if Hasher == "Blake2_128Concat" {
   440  		return types.StorageHasherV10{IsBlake2_128Concat: true}
   441  	}
   442  
   443  	if Hasher == "Twox128" {
   444  		return types.StorageHasherV10{IsTwox128: true}
   445  	}
   446  
   447  	if Hasher == "Twox256" {
   448  		return types.StorageHasherV10{IsTwox256: true}
   449  	}
   450  
   451  	if Hasher == "Twox64Concat" {
   452  		return types.StorageHasherV10{IsTwox64Concat: true}
   453  	}
   454  
   455  	return types.StorageHasherV10{IsIdentity: true}
   456  }
   457  
   458  func (sc *GsrpcClient) sendWsRequest(v interface{}, action []byte) error {
   459  
   460  	retry := 0
   461  	for {
   462  		if retry >= 100 {
   463  			return fmt.Errorf("sendWsRequest reach retry limit")
   464  		}
   465  
   466  		if poolConn, err := sc.initial(); err != nil {
   467  			return err
   468  		} else {
   469  
   470  			if err = poolConn.Conn.WriteMessage(websocket.TextMessage, action); err != nil {
   471  				poolConn.MarkUnusable()
   472  				sc.wsPool.Put(poolConn)
   473  
   474  				sc.log.Debug("websocket send error", "err", err)
   475  				time.Sleep(time.Millisecond * 100)
   476  				retry++
   477  				continue
   478  			}
   479  
   480  			if err = poolConn.Conn.ReadJSON(v); err != nil {
   481  				poolConn.MarkUnusable()
   482  				sc.wsPool.Put(poolConn)
   483  
   484  				sc.log.Debug("websocket read error", "err", err)
   485  				time.Sleep(time.Millisecond * 100)
   486  				retry++
   487  				continue
   488  			}
   489  
   490  			sc.wsPool.Put(poolConn)
   491  			return nil
   492  		}
   493  	}
   494  }
   495  
   496  func (sc *GsrpcClient) GetBlock(blockHash string) (*rpc.Block, error) {
   497  	v := &rpc.JsonRpcResult{}
   498  	if err := sc.sendWsRequest(v, rpc.ChainGetBlock(wsId, blockHash)); err != nil {
   499  		return nil, err
   500  	}
   501  	rpcBlock := v.ToBlock()
   502  	return &rpcBlock.Block, nil
   503  }
   504  
   505  func (sc *GsrpcClient) GetExtrinsics(blockHash string) ([]*Transaction, error) {
   506  	blk, err := sc.GetBlock(blockHash)
   507  	if err != nil {
   508  		return nil, err
   509  	}
   510  
   511  	exts := make([]*Transaction, 0)
   512  	switch sc.chainType {
   513  	case ChainTypeStafi:
   514  		md, err := sc.getStafiMetaDecoder(blockHash)
   515  		if err != nil {
   516  			return nil, err
   517  		}
   518  		e := new(stafi_decoder.ExtrinsicDecoder)
   519  		option := stafi_decoder.ScaleDecoderOption{Metadata: &md.Metadata}
   520  		for _, raw := range blk.Extrinsics {
   521  			e.Init(stafi_decoder.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   522  			e.Process()
   523  			if e.ExtrinsicHash != "" && e.ContainsTransaction {
   524  				ext := &Transaction{
   525  					ExtrinsicHash:  e.ExtrinsicHash,
   526  					CallModuleName: e.CallModule.Name,
   527  					CallName:       e.Call.Name,
   528  					Address:        e.Address,
   529  					Params:         e.Params,
   530  				}
   531  				exts = append(exts, ext)
   532  			}
   533  		}
   534  		return exts, nil
   535  	case ChainTypePolkadot:
   536  		md, err := sc.getPolkaMetaDecoder(blockHash)
   537  		if err != nil {
   538  			return nil, err
   539  		}
   540  		e := new(scalecodec.ExtrinsicDecoder)
   541  		option := scaleTypes.ScaleDecoderOption{Metadata: &md.Metadata}
   542  		for _, raw := range blk.Extrinsics {
   543  			e.Init(scaleBytes.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   544  			e.Process()
   545  			decodeExtrinsic := e.Value.(map[string]interface{})
   546  			var ce ChainExtrinsic
   547  			eb, _ := json.Marshal(decodeExtrinsic)
   548  			_ = json.Unmarshal(eb, &ce)
   549  			if e.ExtrinsicHash != "" && e.ContainsTransaction {
   550  				params := make([]commonTypes.ExtrinsicParam, 0)
   551  				for _, p := range e.Params {
   552  					params = append(params, commonTypes.ExtrinsicParam{
   553  						Name:  p.Name,
   554  						Type:  p.Type,
   555  						Value: p.Value,
   556  					})
   557  				}
   558  
   559  				ext := &Transaction{
   560  					ExtrinsicHash:  e.ExtrinsicHash,
   561  					CallModuleName: ce.CallModule,
   562  					CallName:       ce.CallModuleFunction,
   563  					Address:        e.Address,
   564  					Params:         params,
   565  				}
   566  				exts = append(exts, ext)
   567  			}
   568  		}
   569  		return exts, nil
   570  	default:
   571  		return nil, errors.New("chainType not supported")
   572  	}
   573  }
   574  
   575  func (sc *GsrpcClient) GetBlockHash(blockNum uint64) (string, error) {
   576  	v := &rpc.JsonRpcResult{}
   577  	if err := sc.sendWsRequest(v, rpc.ChainGetBlockHash(wsId, int(blockNum))); err != nil {
   578  		return "", fmt.Errorf("websocket get block hash error: %v", err)
   579  	}
   580  
   581  	blockHash, err := v.ToString()
   582  	if err != nil {
   583  		return "", fmt.Errorf("ChainGetBlockHash get error %v", err)
   584  	}
   585  	if blockHash == "" {
   586  		return "", fmt.Errorf("ChainGetBlockHash error, blockHash empty")
   587  	}
   588  
   589  	return blockHash, nil
   590  }
   591  
   592  func (sc *GsrpcClient) GetChainEvents(blockHash string) ([]*ChainEvent, error) {
   593  	v := &rpc.JsonRpcResult{}
   594  	if err := sc.sendWsRequest(v, rpc.StateGetStorage(wsId, storageKey, blockHash)); err != nil {
   595  		return nil, fmt.Errorf("websocket get event raw error: %v", err)
   596  	}
   597  	eventRaw, err := v.ToString()
   598  	if err != nil {
   599  		return nil, err
   600  	}
   601  
   602  	var events []*ChainEvent
   603  	switch sc.chainType {
   604  	case ChainTypeStafi:
   605  		md, err := sc.getStafiMetaDecoder(blockHash)
   606  		if err != nil {
   607  			return nil, err
   608  		}
   609  		e := stafi_decoder.EventsDecoder{}
   610  		option := stafi_decoder.ScaleDecoderOption{Metadata: &md.Metadata}
   611  		e.Init(stafi_decoder.ScaleBytes{Data: utiles.HexToBytes(eventRaw)}, &option)
   612  		e.Process()
   613  		b, err := json.Marshal(e.Value)
   614  		if err != nil {
   615  			return nil, err
   616  		}
   617  		err = json.Unmarshal(b, &events)
   618  		if err != nil {
   619  			return nil, err
   620  		}
   621  
   622  	case ChainTypePolkadot:
   623  		md, err := sc.getPolkaMetaDecoder(blockHash)
   624  		if err != nil {
   625  			return nil, err
   626  		}
   627  		option := scaleTypes.ScaleDecoderOption{Metadata: &md.Metadata}
   628  
   629  		e := scalecodec.EventsDecoder{}
   630  		e.Init(scaleBytes.ScaleBytes{Data: utiles.HexToBytes(eventRaw)}, &option)
   631  
   632  		e.Process()
   633  
   634  		b, err := json.Marshal(e.Value)
   635  		if err != nil {
   636  			return nil, err
   637  		}
   638  		err = json.Unmarshal(b, &events)
   639  		if err != nil {
   640  			return nil, err
   641  		}
   642  
   643  	default:
   644  		return nil, errors.New("chainType not supported")
   645  	}
   646  
   647  	return events, nil
   648  }
   649  
   650  func (sc *GsrpcClient) GetEvents(blockNum uint64) ([]*ChainEvent, error) {
   651  	blockHash, err := sc.GetBlockHash(blockNum)
   652  	if err != nil {
   653  		return nil, err
   654  	}
   655  
   656  	evts, err := sc.GetChainEvents(blockHash)
   657  	if err != nil {
   658  		return nil, err
   659  	}
   660  
   661  	return evts, nil
   662  }
   663  
   664  func (sc *GsrpcClient) GetBlockTimestampAndExtrinsics(height uint64) (uint64, map[int]*Transaction, error) {
   665  	blockHash, err := sc.GetBlockHash(height)
   666  	if err != nil {
   667  		return 0, nil, err
   668  	}
   669  
   670  	blk, err := sc.GetBlock(blockHash)
   671  	if err != nil {
   672  		return 0, nil, err
   673  	}
   674  	if len(blk.Extrinsics) == 0 {
   675  		return 0, nil, fmt.Errorf("no set time extrinsic in block: %d", height)
   676  	}
   677  
   678  	exts := make(map[int]*Transaction)
   679  	switch sc.chainType {
   680  	case ChainTypeStafi:
   681  		e := new(stafi_decoder.ExtrinsicDecoder)
   682  		md, err := sc.getStafiMetaDecoder(blockHash)
   683  		if err != nil {
   684  			return 0, nil, err
   685  		}
   686  
   687  		option := stafi_decoder.ScaleDecoderOption{Metadata: &md.Metadata, Spec: md.Spec}
   688  
   689  		raw := blk.Extrinsics[0]
   690  		e.Init(stafi_decoder.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   691  		e.Process()
   692  		if len(e.Params) == 0 {
   693  			return 0, nil, fmt.Errorf("no params")
   694  		}
   695  		stamp, ok := e.Params[0].Value.(int)
   696  		if !ok {
   697  			return 0, nil, fmt.Errorf("interface not ok: %s", e.Params[0].Value)
   698  		}
   699  
   700  		for index, raw := range blk.Extrinsics {
   701  			e.Init(stafi_decoder.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   702  			e.Process()
   703  			if e.ExtrinsicHash != "" && e.ContainsTransaction {
   704  				ext := &Transaction{
   705  					ExtrinsicHash:  utiles.AddHex(e.ExtrinsicHash),
   706  					CallModuleName: e.CallModule.Name,
   707  					CallName:       e.Call.Name,
   708  					Address:        e.Address,
   709  					Params:         e.Params,
   710  				}
   711  				exts[index] = ext
   712  			}
   713  		}
   714  		return uint64(stamp), exts, nil
   715  	case ChainTypePolkadot:
   716  		e := new(scalecodec.ExtrinsicDecoder)
   717  		md, err := sc.getPolkaMetaDecoder(blockHash)
   718  		if err != nil {
   719  			return 0, nil, err
   720  		}
   721  		option := scaleTypes.ScaleDecoderOption{Metadata: &md.Metadata, Spec: md.Spec}
   722  
   723  		raw := blk.Extrinsics[0]
   724  		e.Init(scaleBytes.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   725  		e.Process()
   726  
   727  		if len(e.Params) == 0 {
   728  			return 0, nil, fmt.Errorf("no params")
   729  		}
   730  		stamp, ok := e.Params[0].Value.(int)
   731  		if !ok {
   732  			return 0, nil, fmt.Errorf("interface not ok: %s", e.Params[0].Value)
   733  		}
   734  
   735  		for index, raw := range blk.Extrinsics {
   736  			e.Init(scaleBytes.ScaleBytes{Data: utiles.HexToBytes(raw)}, &option)
   737  			e.Process()
   738  
   739  			call, exist := e.Metadata.CallIndex[e.CallIndex]
   740  			if !exist {
   741  				return 0, nil, fmt.Errorf("callIndex: %s not exist metaData", e.CallIndex)
   742  			}
   743  
   744  			if e.ExtrinsicHash != "" && e.ContainsTransaction {
   745  				params := make([]commonTypes.ExtrinsicParam, 0)
   746  				for _, p := range e.Params {
   747  					params = append(params, commonTypes.ExtrinsicParam{
   748  						Name:  p.Name,
   749  						Type:  p.Type,
   750  						Value: p.Value,
   751  					})
   752  				}
   753  				ext := &Transaction{
   754  					ExtrinsicHash:  utiles.AddHex(e.ExtrinsicHash),
   755  					CallModuleName: call.Module.Name,
   756  					CallName:       call.Call.Name,
   757  					Address:        e.Address,
   758  					Params:         params,
   759  				}
   760  				exts[index] = ext
   761  			}
   762  		}
   763  
   764  		return uint64(stamp), exts, nil
   765  	default:
   766  		return 0, nil, errors.New("chainType not supported")
   767  	}
   768  }
   769  
   770  func (sc *GsrpcClient) GetPaymentQueryInfo(encodedExtrinsic string) (paymentInfo *rpc.PaymentQueryInfo, err error) {
   771  	v := &rpc.JsonRpcResult{}
   772  	if err = sc.sendWsRequest(v, rpc.SystemPaymentQueryInfo(wsId, encodedExtrinsic)); err != nil {
   773  		return
   774  	}
   775  
   776  	paymentInfo = v.ToPaymentQueryInfo()
   777  	if paymentInfo == nil {
   778  		return nil, fmt.Errorf("get PaymentQueryInfo error")
   779  	}
   780  	return
   781  }
   782  
   783  func (c *GsrpcClient) CurrentEra() (uint32, error) {
   784  	var index uint32
   785  	exist, err := c.QueryStorage(config.StakingModuleId, config.StorageActiveEra, nil, nil, &index)
   786  	if err != nil {
   787  		return 0, err
   788  	}
   789  
   790  	if !exist {
   791  		return 0, fmt.Errorf("unable to get activeEraInfo")
   792  	}
   793  
   794  	return index, nil
   795  }