github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/mobile/mysterium/identity.go (about) 1 /* 2 * Copyright (C) 2021 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package mysterium 19 20 import ( 21 "encoding/json" 22 "errors" 23 "fmt" 24 "math/big" 25 26 "github.com/mysteriumnetwork/node/identity" 27 "github.com/mysteriumnetwork/node/identity/registry" 28 "github.com/mysteriumnetwork/payments/crypto" 29 ) 30 31 // GetIdentityRequest represents identity request. 32 type GetIdentityRequest struct { 33 Address string 34 Passphrase string 35 } 36 37 // GetIdentityResponse represents identity response. 38 type GetIdentityResponse struct { 39 IdentityAddress string 40 ChannelAddress string 41 RegistrationStatus string 42 } 43 44 // GetIdentity finds first identity and unlocks it. 45 // If there is no identity default one will be created. 46 func (mb *MobileNode) GetIdentity(req *GetIdentityRequest) (*GetIdentityResponse, error) { 47 if req == nil { 48 req = &GetIdentityRequest{} 49 } 50 51 id, err := mb.identitySelector.UseOrCreate(req.Address, req.Passphrase, mb.chainID) 52 if err != nil { 53 return nil, fmt.Errorf("could not unlock identity: %w", err) 54 } 55 56 channelAddress, err := mb.identityChannelCalculator.GetActiveChannelAddress(mb.chainID, id.ToCommonAddress()) 57 if err != nil { 58 return nil, fmt.Errorf("could not generate channel address: %w", err) 59 } 60 61 status, err := mb.identityRegistry.GetRegistrationStatus(mb.chainID, id) 62 if err != nil { 63 return nil, fmt.Errorf("could not get identity registration status: %w", err) 64 } 65 66 return &GetIdentityResponse{ 67 IdentityAddress: id.Address, 68 ChannelAddress: channelAddress.Hex(), 69 RegistrationStatus: status.String(), 70 }, nil 71 } 72 73 // GetIdentityRegistrationFeesResponse represents identity registration fees result. 74 type GetIdentityRegistrationFeesResponse struct { 75 Fee float64 76 } 77 78 // GetIdentityRegistrationFees returns identity registration fees. 79 func (mb *MobileNode) GetIdentityRegistrationFees() (*GetIdentityRegistrationFeesResponse, error) { 80 fees, err := mb.transactor.FetchRegistrationFees(mb.chainID) 81 if err != nil { 82 return nil, fmt.Errorf("could not get registration fees: %w", err) 83 } 84 85 fee := crypto.BigMystToFloat(fees.Fee) 86 87 return &GetIdentityRegistrationFeesResponse{Fee: fee}, nil 88 } 89 90 // RegisterIdentityRequest represents identity registration request. 91 type RegisterIdentityRequest struct { 92 IdentityAddress string 93 Token string 94 } 95 96 // RegisterIdentity starts identity registration in background. 97 func (mb *MobileNode) RegisterIdentity(req *RegisterIdentityRequest) error { 98 fees, err := mb.transactor.FetchRegistrationFees(mb.chainID) 99 if err != nil { 100 return fmt.Errorf("could not get registration fees: %w", err) 101 } 102 103 var token *string 104 if req.Token != "" { 105 token = &req.Token 106 } 107 108 err = mb.transactor.RegisterIdentity(req.IdentityAddress, big.NewInt(0), fees.Fee, "", mb.chainID, token) 109 if err != nil { 110 return fmt.Errorf("could not register identity: %w", err) 111 } 112 113 return nil 114 } 115 116 // IdentityRegistrationChangeCallback represents identity registration status callback. 117 type IdentityRegistrationChangeCallback interface { 118 OnChange(identityAddress string, status string) 119 } 120 121 // RegisterIdentityRegistrationChangeCallback registers callback which is called on identity registration status change. 122 func (mb *MobileNode) RegisterIdentityRegistrationChangeCallback(cb IdentityRegistrationChangeCallback) { 123 _ = mb.eventBus.SubscribeAsync(registry.AppTopicIdentityRegistration, func(e registry.AppEventIdentityRegistration) { 124 cb.OnChange(e.ID.Address, e.Status.String()) 125 }) 126 } 127 128 // ExportIdentity exports a given identity address encrypting it with the new passphrase. 129 func (mb *MobileNode) ExportIdentity(identityAddress, newPassphrase string) ([]byte, error) { 130 data, err := mb.identityMover.Export(identityAddress, "", newPassphrase) 131 if err != nil { 132 return nil, err 133 } 134 135 return data, nil 136 } 137 138 // ImportIdentity import a given identity address given data (json as string) and the 139 // current passphrase. 140 // 141 // Identity can only be imported if it is registered. 142 func (mb *MobileNode) ImportIdentity(data []byte, passphrase string) (string, error) { 143 identity, err := mb.identityMover.Import(data, passphrase, "") 144 if err != nil { 145 return "", err 146 } 147 148 return identity.Address, nil 149 } 150 151 // IsFreeRegistrationEligible returns true if free registration is possible for a given identity. 152 func (mb *MobileNode) IsFreeRegistrationEligible(identityAddress string) (bool, error) { 153 id := identity.FromAddress(identityAddress) 154 ok, err := mb.transactor.GetFreeRegistrationEligibility(id) 155 if err != nil { 156 return false, err 157 } 158 159 return ok, nil 160 } 161 162 // RegistrationTokenReward returns the reward amount for a given token. 163 func (mb *MobileNode) RegistrationTokenReward(token string) (float64, error) { 164 reward, err := mb.affiliator.RegistrationTokenReward(token) 165 if err != nil { 166 return 0, err 167 } 168 if reward == nil { 169 return 0, errors.New("failed to return reward") 170 } 171 172 return crypto.BigMystToFloat(reward), nil 173 } 174 175 // MigrateHermes migrate from old to active Hermes 176 func (mb *MobileNode) MigrateHermes(id string) error { 177 return mb.hermesMigrator.Start(id) 178 } 179 180 const ( 181 // MigrationStatusRequired means new there is new Hermes and identity required to migrate to it 182 MigrationStatusRequired = "required" 183 // MigrationStatusFinished means migration to new Hermes finished or not needed 184 MigrationStatusFinished = "finished" 185 ) 186 187 // MigrationStatusResponse represents status of the migration 188 type MigrationStatusResponse struct { 189 Status MigrationStatus `json:"status"` 190 } 191 192 // MigrationStatus status of the migration 193 type MigrationStatus = string 194 195 // MigrateHermesStatus migrate from old to active Hermes 196 func (mb *MobileNode) MigrateHermesStatus(id string) ([]byte, error) { 197 r, err := mb.hermesMigrator.IsMigrationRequired(id) 198 if err != nil { 199 return []byte{}, err 200 } 201 202 var status MigrationStatus 203 if r { 204 status = MigrationStatusRequired 205 } else { 206 status = MigrationStatusFinished 207 } 208 209 return json.Marshal(MigrationStatusResponse{Status: status}) 210 }