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

     1  package client
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/stafiprotocol/go-substrate-rpc-client/config"
     8  	"github.com/stafiprotocol/go-substrate-rpc-client/rpc/author"
     9  	"github.com/stafiprotocol/go-substrate-rpc-client/types"
    10  )
    11  
    12  func (sc *GsrpcClient) NewUnsignedExtrinsic(callMethod string, args ...interface{}) (interface{}, error) {
    13  	sc.log.Debug("Submitting substrate call...", "callMethod", callMethod, "addressType", sc.addressType, "sender", sc.key.Address)
    14  
    15  	ci, err := sc.FindCallIndex(callMethod)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	call, err := types.NewCallWithCallIndex(ci, callMethod, args...)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	if sc.addressType == AddressTypeAccountId {
    25  		unsignedExt := types.NewExtrinsic(call)
    26  		return &unsignedExt, nil
    27  	} else if sc.addressType == AddressTypeMultiAddress {
    28  		unsignedExt := types.NewExtrinsicMulti(call)
    29  		return &unsignedExt, nil
    30  	} else {
    31  		return nil, errors.New("addressType not supported")
    32  	}
    33  }
    34  
    35  func (sc *GsrpcClient) SignAndSubmitTx(ext interface{}) error {
    36  	err := sc.signExtrinsic(ext)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	sc.log.Trace("signExtrinsic ok")
    41  
    42  	api, err := sc.FlashApi()
    43  	if err != nil {
    44  		return err
    45  	}
    46  	sc.log.Trace("flashApi ok")
    47  	// Do the transfer and track the actual status
    48  	sub, err := api.Author.SubmitAndWatch(ext)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	sc.log.Trace("Extrinsic submission succeeded")
    53  	defer sub.Unsubscribe()
    54  
    55  	return sc.watchSubmission(sub)
    56  }
    57  
    58  func (sc *GsrpcClient) watchSubmission(sub *author.ExtrinsicStatusSubscription) error {
    59  	for {
    60  		select {
    61  		case status := <-sub.Chan():
    62  			switch {
    63  			case status.IsInBlock:
    64  				sc.log.Info("Extrinsic included in block", "block", status.AsInBlock.Hex())
    65  				return nil
    66  			case status.IsRetracted:
    67  				return fmt.Errorf("extrinsic retracted: %s", status.AsRetracted.Hex())
    68  			case status.IsDropped:
    69  				return fmt.Errorf("extrinsic dropped from network")
    70  			case status.IsInvalid:
    71  				return fmt.Errorf("extrinsic invalid")
    72  			}
    73  		case err := <-sub.Err():
    74  			sc.log.Trace("Extrinsic subscription error", "err", err)
    75  			return err
    76  		}
    77  	}
    78  }
    79  
    80  func (sc *GsrpcClient) signExtrinsic(xt interface{}) error {
    81  	rv, err := sc.GetLatestRuntimeVersion()
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	nonce, err := sc.GetLatestNonce()
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	o := types.SignatureOptions{
    92  		BlockHash:          sc.genesisHash,
    93  		Era:                types.ExtrinsicEra{IsMortalEra: false},
    94  		GenesisHash:        sc.genesisHash,
    95  		Nonce:              types.NewUCompactFromUInt(uint64(nonce)),
    96  		SpecVersion:        rv.SpecVersion,
    97  		Tip:                types.NewUCompactFromUInt(0),
    98  		TransactionVersion: rv.TransactionVersion,
    99  	}
   100  
   101  	if ext, ok := xt.(*types.Extrinsic); ok {
   102  		sc.log.Debug("signExtrinsic", "addressType", sc.addressType)
   103  		err = ext.Sign(*sc.key, o)
   104  		if err != nil {
   105  			return err
   106  		}
   107  	} else if ext, ok := xt.(*types.ExtrinsicMulti); ok {
   108  		sc.log.Debug("signExtrinsic", "addressType", sc.addressType)
   109  		err = ext.Sign(*sc.key, o)
   110  		if err != nil {
   111  			return fmt.Errorf("sign err: %s", err)
   112  		}
   113  	} else {
   114  		return errors.New("extrinsic cast error")
   115  	}
   116  
   117  	return nil
   118  }
   119  
   120  func (sc *GsrpcClient) SingleTransferTo(accountId []byte, value types.UCompact) error {
   121  	var addr interface{}
   122  	switch sc.addressType {
   123  	case AddressTypeAccountId:
   124  		addr = types.NewAddressFromAccountID(accountId)
   125  	case AddressTypeMultiAddress:
   126  		addr = types.NewMultiAddressFromAccountID(accountId)
   127  	default:
   128  		return fmt.Errorf("unsupported address type: %s", sc.addressType)
   129  	}
   130  	ext, err := sc.NewUnsignedExtrinsic(config.MethodTransferKeepAlive, addr, value)
   131  	if err != nil {
   132  		return err
   133  	}
   134  	return sc.SignAndSubmitTx(ext)
   135  }