github.com/ava-labs/avalanchego@v1.11.11/vms/components/avax/addresses.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package avax 5 6 import ( 7 "errors" 8 "fmt" 9 10 "github.com/ava-labs/avalanchego/ids" 11 "github.com/ava-labs/avalanchego/snow" 12 "github.com/ava-labs/avalanchego/utils/constants" 13 "github.com/ava-labs/avalanchego/utils/formatting/address" 14 "github.com/ava-labs/avalanchego/utils/set" 15 ) 16 17 var ( 18 _ AddressManager = (*addressManager)(nil) 19 20 ErrMismatchedChainIDs = errors.New("mismatched chainIDs") 21 ) 22 23 type AddressManager interface { 24 // ParseLocalAddress takes in an address for this chain and produces the ID 25 ParseLocalAddress(addrStr string) (ids.ShortID, error) 26 27 // ParseAddress takes in an address and produces the ID of the chain it's 28 // for and the ID of the address 29 ParseAddress(addrStr string) (ids.ID, ids.ShortID, error) 30 31 // FormatLocalAddress takes in a raw address and produces the formatted 32 // address for this chain 33 FormatLocalAddress(addr ids.ShortID) (string, error) 34 35 // FormatAddress takes in a chainID and a raw address and produces the 36 // formatted address for that chain 37 FormatAddress(chainID ids.ID, addr ids.ShortID) (string, error) 38 } 39 40 type addressManager struct { 41 ctx *snow.Context 42 } 43 44 func NewAddressManager(ctx *snow.Context) AddressManager { 45 return &addressManager{ 46 ctx: ctx, 47 } 48 } 49 50 func (a *addressManager) ParseLocalAddress(addrStr string) (ids.ShortID, error) { 51 chainID, addr, err := a.ParseAddress(addrStr) 52 if err != nil { 53 return ids.ShortID{}, err 54 } 55 if chainID != a.ctx.ChainID { 56 return ids.ShortID{}, fmt.Errorf( 57 "%w: expected %q but got %q", 58 ErrMismatchedChainIDs, 59 a.ctx.ChainID, 60 chainID, 61 ) 62 } 63 return addr, nil 64 } 65 66 func (a *addressManager) ParseAddress(addrStr string) (ids.ID, ids.ShortID, error) { 67 chainIDAlias, hrp, addrBytes, err := address.Parse(addrStr) 68 if err != nil { 69 return ids.Empty, ids.ShortID{}, err 70 } 71 72 chainID, err := a.ctx.BCLookup.Lookup(chainIDAlias) 73 if err != nil { 74 return ids.Empty, ids.ShortID{}, err 75 } 76 77 expectedHRP := constants.GetHRP(a.ctx.NetworkID) 78 if hrp != expectedHRP { 79 return ids.Empty, ids.ShortID{}, fmt.Errorf( 80 "expected hrp %q but got %q", 81 expectedHRP, 82 hrp, 83 ) 84 } 85 86 addr, err := ids.ToShortID(addrBytes) 87 if err != nil { 88 return ids.Empty, ids.ShortID{}, err 89 } 90 return chainID, addr, nil 91 } 92 93 func (a *addressManager) FormatLocalAddress(addr ids.ShortID) (string, error) { 94 return a.FormatAddress(a.ctx.ChainID, addr) 95 } 96 97 func (a *addressManager) FormatAddress(chainID ids.ID, addr ids.ShortID) (string, error) { 98 chainIDAlias, err := a.ctx.BCLookup.PrimaryAlias(chainID) 99 if err != nil { 100 return "", err 101 } 102 hrp := constants.GetHRP(a.ctx.NetworkID) 103 return address.Format(chainIDAlias, hrp, addr.Bytes()) 104 } 105 106 func ParseLocalAddresses(a AddressManager, addrStrs []string) (set.Set[ids.ShortID], error) { 107 addrs := make(set.Set[ids.ShortID], len(addrStrs)) 108 for _, addrStr := range addrStrs { 109 addr, err := a.ParseLocalAddress(addrStr) 110 if err != nil { 111 return nil, fmt.Errorf("couldn't parse address %q: %w", addrStr, err) 112 } 113 addrs.Add(addr) 114 } 115 return addrs, nil 116 } 117 118 // ParseServiceAddress get address ID from address string, being it either localized (using address manager, 119 // doing also components validations), or not localized. 120 // If both attempts fail, reports error from localized address parsing 121 func ParseServiceAddress(a AddressManager, addrStr string) (ids.ShortID, error) { 122 addr, err := ids.ShortFromString(addrStr) 123 if err == nil { 124 return addr, nil 125 } 126 127 addr, err = a.ParseLocalAddress(addrStr) 128 if err != nil { 129 return addr, fmt.Errorf("couldn't parse address %q: %w", addrStr, err) 130 } 131 return addr, nil 132 } 133 134 // ParseServiceAddresses get addresses IDs from addresses strings, being them either localized or not 135 func ParseServiceAddresses(a AddressManager, addrStrs []string) (set.Set[ids.ShortID], error) { 136 addrs := set.NewSet[ids.ShortID](len(addrStrs)) 137 for _, addrStr := range addrStrs { 138 addr, err := ParseServiceAddress(a, addrStr) 139 if err != nil { 140 return nil, err 141 } 142 addrs.Add(addr) 143 } 144 return addrs, nil 145 }