code.vegaprotocol.io/vega@v0.79.0/wallet/version/version.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package version 17 18 import ( 19 "errors" 20 "sort" 21 "strings" 22 23 vgversion "code.vegaprotocol.io/vega/libs/version" 24 coreversion "code.vegaprotocol.io/vega/version" 25 "code.vegaprotocol.io/vega/wallet/network" 26 ) 27 28 var ErrCouldNotListNetworks = errors.New("couldn't list the networks") 29 30 // RequestVersionFn is the function in charge of retrieving the network version 31 // ran by the host lists. 32 type RequestVersionFn func(hosts []string) (string, error) 33 34 //go:generate go run github.com/golang/mock/mockgen -destination mocks/store_mock.go -package mocks code.vegaprotocol.io/vega/wallet/version NetworkStore 35 type NetworkStore interface { 36 ListNetworks() ([]string, error) 37 GetNetwork(string) (*network.Network, error) 38 } 39 40 func IsUnreleased() bool { 41 return vgversion.IsUnreleased(coreversion.Get()) 42 } 43 44 type GetSoftwareVersionResponse struct { 45 Version string `json:"version"` 46 GitHash string `json:"gitHash"` 47 } 48 49 func GetSoftwareVersionInfo() *GetSoftwareVersionResponse { 50 response := &GetSoftwareVersionResponse{ 51 Version: coreversion.Get(), 52 GitHash: coreversion.GetCommitHash(), 53 } 54 55 return response 56 } 57 58 type CheckSoftwareCompatibilityResponse struct { 59 NetworksCompatibility []NetworkCompatibility `json:"networksCompatibility"` 60 } 61 62 type NetworkCompatibility struct { 63 Network string `json:"network"` 64 IsCompatible bool `json:"isCompatible"` 65 RetrievedVersion string `json:"retrievedVersion"` 66 Error error `json:"error"` 67 } 68 69 func CheckSoftwareCompatibility(netStore NetworkStore, requestVersionFn RequestVersionFn) (*CheckSoftwareCompatibilityResponse, error) { 70 networks, err := netStore.ListNetworks() 71 // If there's an error we don't fail the command as the compatibility matrix 72 // is just a nice to have. 73 if err != nil { 74 // Best-effort, so we don't fail. 75 return nil, ErrCouldNotListNetworks 76 } 77 78 networksCompatibility := make([]NetworkCompatibility, 0, len(networks)) 79 80 coreVersion := coreversion.Get() 81 coreVersionForComparison := onlyMajorAndMinor(coreVersion) 82 83 for _, net := range networks { 84 networkCompatibility := NetworkCompatibility{ 85 Network: net, 86 } 87 88 netConfig, err := netStore.GetNetwork(net) 89 if err != nil { 90 // Best-effort, so we don't fail. 91 networkCompatibility.Error = err 92 networksCompatibility = append(networksCompatibility, networkCompatibility) 93 continue 94 } 95 96 if err := netConfig.EnsureCanConnectGRPCNode(); err != nil { 97 // Best-effort, so we don't fail. 98 networkCompatibility.Error = err 99 networksCompatibility = append(networksCompatibility, networkCompatibility) 100 continue 101 } 102 103 networkVersion, err := requestVersionFn(netConfig.API.GRPC.Hosts) 104 if err != nil { 105 // Best-effort, so we don't fail. 106 networkCompatibility.Error = err 107 networksCompatibility = append(networksCompatibility, networkCompatibility) 108 continue 109 } 110 111 networkCompatibility.RetrievedVersion = networkVersion 112 networkVersionForComparison := onlyMajorAndMinor(networkVersion) 113 114 if networkVersionForComparison != coreVersionForComparison { 115 networkCompatibility.IsCompatible = false 116 networksCompatibility = append(networksCompatibility, networkCompatibility) 117 continue 118 } 119 120 networkCompatibility.IsCompatible = true 121 networksCompatibility = append(networksCompatibility, networkCompatibility) 122 } 123 124 // Ensure the output is determinist. 125 sort.Slice(networksCompatibility, func(a, b int) bool { 126 return networksCompatibility[a].Network < networksCompatibility[b].Network 127 }) 128 129 return &CheckSoftwareCompatibilityResponse{ 130 NetworksCompatibility: networksCompatibility, 131 }, nil 132 } 133 134 func onlyMajorAndMinor(version string) string { 135 segments := strings.Split(version, ".") 136 if len(segments) < 2 { 137 // It doesn't seem to be a valid semantic version. 138 return version 139 } 140 141 return segments[0] + "." + segments[1] 142 }