github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/beneficiary/change_keeper.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 beneficiary 19 20 import ( 21 "fmt" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/mysteriumnetwork/node/identity" 25 "github.com/rs/zerolog/log" 26 ) 27 28 // SettleState represents the state of settle with beneficiary transaction 29 type SettleState string 30 31 const ( 32 // Pending transaction is pending 33 Pending SettleState = "pending" 34 // Completed transaction is completed 35 Completed SettleState = "completed" 36 // NotFound transaction state 37 NotFound SettleState = "not_found" 38 39 bucketChangeStatus = "beneficiary-change-status" 40 ) 41 42 type beneficiaryChangeKeeper struct { 43 st storage 44 chainID int64 45 } 46 47 func newBeneficiaryChangeKeeper(chainID int64, st storage) *beneficiaryChangeKeeper { 48 return &beneficiaryChangeKeeper{ 49 chainID: chainID, 50 st: st, 51 } 52 } 53 54 // ChangeStatus holds Beneficiary settlement transaction information 55 type ChangeStatus struct { 56 ChangeTo string 57 State SettleState 58 Error string 59 } 60 61 func newChangeStatus(changeTo string, state SettleState, err error) *ChangeStatus { 62 n := &ChangeStatus{ 63 ChangeTo: changeTo, 64 State: state, 65 Error: "", 66 } 67 68 if err != nil { 69 n.Error = err.Error() 70 } 71 72 return n 73 } 74 75 func (bcs *beneficiaryChangeKeeper) updateChangeStatus(id identity.Identity, sbs SettleState, beneficiary string, settleError error) (*ChangeStatus, error) { 76 entry := newChangeStatus(beneficiary, sbs, settleError) 77 err := bcs.st.SetValue(bucketChangeStatus, storageKey(bcs.chainID, id.Address), entry) 78 if err != nil { 79 return nil, err 80 } 81 82 return entry, nil 83 } 84 85 func (bcs *beneficiaryChangeKeeper) executeWithStatusTracking(id identity.Identity, bf common.Address, fn func() error) error { 86 if _, err := bcs.updateChangeStatus(id, Pending, bf.Hex(), nil); err != nil { 87 return fmt.Errorf("failed to start tracking status change: %w", err) 88 } 89 callbackErr := fn() 90 91 if _, err := bcs.updateChangeStatus(id, Completed, bf.Hex(), callbackErr); err != nil { 92 log.Err(err).Msg("saving beneficiary change status") 93 } 94 95 return callbackErr 96 } 97 98 // GetChangeStatus returns current change transaction status. 99 func (bcs *beneficiaryChangeKeeper) GetChangeStatus(id identity.Identity) (*ChangeStatus, error) { 100 var b ChangeStatus 101 if err := bcs.st.GetValue(bucketChangeStatus, storageKey(bcs.chainID, id.Address), &b); err != nil { 102 return nil, err 103 } 104 return &b, nil 105 } 106 107 // CleanupAndGetChangeStatus cleans up current change status and returns it. 108 // 109 // Cleanup is done using the provided currentBeneficiary, if the beneficiaries match 110 // and transaction is still in state "Pending" it will be bumped to completed, else 111 // nothing is done. 112 func (bcs *beneficiaryChangeKeeper) CleanupAndGetChangeStatus(id identity.Identity, currentBeneficiary string) (*ChangeStatus, error) { 113 b, err := bcs.GetChangeStatus(id) 114 if err != nil { 115 return nil, err 116 } 117 118 // Not pending, no need to cleanup. 119 if b.State != Pending { 120 return b, nil 121 } 122 123 if b.ChangeTo != currentBeneficiary { 124 return b, nil 125 } 126 127 return bcs.updateChangeStatus(id, Completed, currentBeneficiary, nil) 128 }