github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/session/pingpong/settlement_history_storage.go (about) 1 /* 2 * Copyright (C) 2020 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 pingpong 19 20 import ( 21 "errors" 22 "math/big" 23 "time" 24 25 "github.com/asdine/storm/v3" 26 "github.com/asdine/storm/v3/q" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/mysteriumnetwork/node/core/storage/boltdb" 29 "github.com/mysteriumnetwork/node/identity" 30 "github.com/mysteriumnetwork/payments/crypto" 31 ) 32 33 // HistoryType settlement history type 34 // swagger:model HistoryType 35 type HistoryType string 36 37 const ( 38 // SettlementType settlement type 39 SettlementType HistoryType = "settlement" 40 // WithdrawalType withdrawal type 41 WithdrawalType HistoryType = "withdrawal" 42 ) 43 44 // SettlementHistoryStorage stores the settlement events for historical purposes. 45 type SettlementHistoryStorage struct { 46 bolt *boltdb.Bolt 47 } 48 49 // NewSettlementHistoryStorage returns a new instance of the SettlementHistoryStorage. 50 func NewSettlementHistoryStorage(bolt *boltdb.Bolt) *SettlementHistoryStorage { 51 return &SettlementHistoryStorage{ 52 bolt: bolt, 53 } 54 } 55 56 // SettlementHistoryEntry represents a settlement history entry 57 type SettlementHistoryEntry struct { 58 TxHash common.Hash `storm:"id"` 59 BlockExplorerURL string 60 ProviderID identity.Identity 61 HermesID common.Address 62 ChannelAddress common.Address 63 Time time.Time 64 Promise crypto.Promise 65 Beneficiary common.Address 66 Amount *big.Int 67 TotalSettled *big.Int 68 Fees *big.Int 69 IsWithdrawal bool 70 Error string 71 } 72 73 const settlementHistoryBucket = "settlement-history" 74 75 // Store stores a given settlement history entry. 76 func (shs *SettlementHistoryStorage) Store(she SettlementHistoryEntry) error { 77 shs.bolt.Lock() 78 defer shs.bolt.Unlock() 79 return shs.bolt.DB().From(settlementHistoryBucket).Save(&she) 80 } 81 82 // SettlementHistoryFilter defines all flags for filtering in settlement history storage. 83 type SettlementHistoryFilter struct { 84 TimeFrom *time.Time 85 TimeTo *time.Time 86 ProviderID *identity.Identity 87 HermesID *common.Address 88 Types []HistoryType 89 } 90 91 // List retrieves stored entries. 92 func (shs *SettlementHistoryStorage) List(filter SettlementHistoryFilter) (result []SettlementHistoryEntry, err error) { 93 where := make([]q.Matcher, 0) 94 if filter.TimeFrom != nil { 95 where = append(where, q.Gte("Time", filter.TimeFrom.UTC())) 96 } 97 if filter.TimeTo != nil { 98 where = append(where, q.Lte("Time", filter.TimeTo.UTC())) 99 } 100 if filter.ProviderID != nil { 101 id := filter.ProviderID 102 where = append(where, q.Eq("ProviderID", *id)) 103 } 104 if filter.HermesID != nil { 105 where = append(where, q.Eq("HermesID", filter.HermesID)) 106 } 107 if len(filter.Types) > 0 { 108 if contains(filter.Types, WithdrawalType) { 109 where = append(where, q.Eq("IsWithdrawal", true)) 110 } 111 if contains(filter.Types, SettlementType) { 112 where = append(where, q.Eq("IsWithdrawal", false)) 113 } 114 } 115 116 shs.bolt.RLock() 117 defer shs.bolt.RUnlock() 118 sq := shs.bolt.DB(). 119 From(settlementHistoryBucket). 120 Select(q.And(where...)). 121 OrderBy("Time"). 122 Reverse() 123 124 err = sq.Find(&result) 125 if errors.Is(err, storm.ErrNotFound) { 126 return []SettlementHistoryEntry{}, nil 127 } 128 129 return result, err 130 } 131 132 func contains(sources []HistoryType, target HistoryType) bool { 133 for _, source := range sources { 134 if source == target { 135 return true 136 } 137 } 138 139 return false 140 }