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

     1  // Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls
     2  //
     3  // Copyright 2020 Stafi Protocol
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package types
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/stafiprotocol/go-substrate-rpc-client/pkg/scale"
    23  )
    24  
    25  // Address is a wrapper around an AccountId or an AccountIndex. It is encoded with a prefix in case of an AccountID.
    26  // Basically the Address is encoded as `[ <prefix-byte>, ...publicKey/...bytes ]` as per spec
    27  type Address struct {
    28  	IsAccountID    bool
    29  	AsAccountID    AccountID
    30  	IsAccountIndex bool
    31  	AsAccountIndex AccountIndex
    32  }
    33  
    34  // NewAddressFromAccountID creates an Address from the given AccountID (public key)
    35  func NewAddressFromAccountID(b []byte) Address {
    36  	return Address{
    37  		IsAccountID: true,
    38  		AsAccountID: NewAccountID(b),
    39  	}
    40  }
    41  
    42  // NewAddressFromHexAccountID creates an Address from the given hex string that contains an AccountID (public key)
    43  func NewAddressFromHexAccountID(str string) (Address, error) {
    44  	b, err := HexDecodeString(str)
    45  	if err != nil {
    46  		return Address{}, err
    47  	}
    48  	return NewAddressFromAccountID(b), nil
    49  }
    50  
    51  // NewAddressFromAccountIndex creates an Address from the given AccountIndex
    52  func NewAddressFromAccountIndex(u uint32) Address {
    53  	return Address{
    54  		IsAccountIndex: true,
    55  		AsAccountIndex: AccountIndex(u),
    56  	}
    57  }
    58  
    59  func (a *Address) Decode(decoder scale.Decoder) error {
    60  	b, err := decoder.ReadOneByte()
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	if defaultOptions.NoPalletIndices {
    66  		var sm [31]byte // Reading Address[32] minus b already read
    67  		err = decoder.Decode(&sm)
    68  		if err != nil {
    69  			return err
    70  		}
    71  		a.AsAccountID = NewAccountID(append([]byte{b}, sm[:]...)) // Push b back to the front
    72  		a.IsAccountID = true
    73  		return nil
    74  	}
    75  
    76  	if b == 0xff {
    77  		err = decoder.Decode(&a.AsAccountID)
    78  		a.IsAccountID = true
    79  		return err
    80  	}
    81  
    82  	if b == 0xfe {
    83  		return fmt.Errorf("decoding of Address with 0xfe prefix not supported")
    84  	}
    85  
    86  	if b == 0xfd {
    87  		err = decoder.Decode(&a.AsAccountIndex)
    88  		a.IsAccountIndex = true
    89  		return err
    90  	}
    91  
    92  	if b == 0xfc {
    93  		var aIndex uint16
    94  		err = decoder.Decode(&aIndex)
    95  		a.IsAccountIndex = true
    96  		a.AsAccountIndex = AccountIndex(aIndex)
    97  		return err
    98  	}
    99  
   100  	a.IsAccountIndex = true
   101  	a.AsAccountIndex = AccountIndex(b)
   102  	return nil
   103  }
   104  
   105  func (a Address) Encode(encoder scale.Encoder) error {
   106  	// type of address - public key
   107  	if a.IsAccountID {
   108  		if !defaultOptions.NoPalletIndices { // Skip in case target chain doesn't include indices pallet
   109  			err := encoder.PushByte(255)
   110  			if err != nil {
   111  				return err
   112  			}
   113  		}
   114  
   115  		err := encoder.Write(a.AsAccountID[:])
   116  		if err != nil {
   117  			return err
   118  		}
   119  
   120  		return nil
   121  	}
   122  
   123  	if a.AsAccountIndex > 0xffff {
   124  		err := encoder.PushByte(253)
   125  		if err != nil {
   126  			return err
   127  		}
   128  
   129  		return encoder.Encode(a.AsAccountIndex)
   130  	}
   131  
   132  	if a.AsAccountIndex >= 0xf0 {
   133  		err := encoder.PushByte(252)
   134  		if err != nil {
   135  			return err
   136  		}
   137  
   138  		return encoder.Encode(uint16(a.AsAccountIndex))
   139  	}
   140  
   141  	return encoder.Encode(uint8(a.AsAccountIndex))
   142  }