github.com/status-im/status-go@v1.1.0/services/wallet/transfer/multi_transaction_db.go (about) 1 package transfer 2 3 import ( 4 "database/sql" 5 "fmt" 6 "strings" 7 8 "github.com/ethereum/go-ethereum/common" 9 wallet_common "github.com/status-im/status-go/services/wallet/common" 10 ) 11 12 // Since we already use MultitransactionIDType in DB, and its default value is 0 (Send) 13 // this type is used to with default value 0 to represent invalid type to avoid bugs 14 // when devs forget to call NewMultiTxDetails() 15 type MultiTransactionDBType MultiTransactionType 16 17 const ( 18 MultiTransactionDBTypeInvalid = 0 19 MultiTransactionDBSend = iota 20 MultiTransactionDBSwap 21 MultiTransactionDBBridge 22 MultiTransactionDBApprove 23 ) 24 25 func mtDBTypeToMTType(mtDBType MultiTransactionDBType) MultiTransactionType { 26 if mtDBType == MultiTransactionDBTypeInvalid { 27 return MultiTransactionTypeInvalid 28 } 29 30 return MultiTransactionType(mtDBType - 1) 31 } 32 33 type MultiTxDetails struct { 34 IDs []wallet_common.MultiTransactionIDType 35 AnyAddress common.Address 36 FromAddress common.Address 37 ToAddress common.Address 38 ToChainID uint64 39 CrossTxID string 40 Type MultiTransactionDBType 41 } 42 43 func NewMultiTxDetails() *MultiTxDetails { 44 return &MultiTxDetails{} 45 } 46 47 type MultiTransactionDB struct { 48 db *sql.DB 49 } 50 51 func NewMultiTransactionDB(db *sql.DB) *MultiTransactionDB { 52 return &MultiTransactionDB{ 53 db: db, 54 } 55 } 56 57 func (mtDB *MultiTransactionDB) CreateMultiTransaction(multiTransaction *MultiTransaction) error { 58 insert, err := mtDB.db.Prepare(fmt.Sprintf(`INSERT INTO multi_transactions (%s) 59 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, multiTransactionColumns)) 60 if err != nil { 61 return err 62 } 63 _, err = insert.Exec( 64 multiTransaction.ID, 65 multiTransaction.FromNetworkID, 66 multiTransaction.FromTxHash, 67 multiTransaction.FromAddress, 68 multiTransaction.FromAsset, 69 multiTransaction.FromAmount.String(), 70 multiTransaction.ToNetworkID, 71 multiTransaction.ToTxHash, 72 multiTransaction.ToAddress, 73 multiTransaction.ToAsset, 74 multiTransaction.ToAmount.String(), 75 multiTransaction.Type, 76 multiTransaction.CrossTxID, 77 multiTransaction.Timestamp, 78 ) 79 if err != nil { 80 return err 81 } 82 defer insert.Close() 83 84 return err 85 } 86 87 func (mtDB *MultiTransactionDB) ReadMultiTransactions(details *MultiTxDetails) ([]*MultiTransaction, error) { 88 if details == nil { 89 return nil, fmt.Errorf("details is nil") 90 } 91 92 whereClause := "" 93 94 args := []interface{}{} 95 96 if len(details.IDs) > 0 { 97 placeholders := make([]string, len(details.IDs)) 98 for i, v := range details.IDs { 99 placeholders[i] = "?" 100 args = append(args, v) 101 } 102 whereClause += fmt.Sprintf("id in (%s) AND ", strings.Join(placeholders, ",")) 103 } 104 if (details.AnyAddress != common.Address{}) { 105 whereClause += "(from_address=? OR to_address=?) AND " 106 args = append(args, details.AnyAddress, details.AnyAddress) 107 } 108 if (details.FromAddress != common.Address{}) { 109 whereClause += "from_address=? AND " 110 args = append(args, details.FromAddress) 111 } 112 if (details.ToAddress != common.Address{}) { 113 whereClause += "to_address=? AND " 114 args = append(args, details.ToAddress) 115 } 116 if details.ToChainID != 0 { 117 whereClause += "to_network_id=? AND " 118 args = append(args, details.ToChainID) 119 } 120 if details.CrossTxID != "" { 121 whereClause += "cross_tx_id=? AND " 122 args = append(args, details.CrossTxID) 123 } 124 if details.Type != MultiTransactionDBTypeInvalid { 125 whereClause += "type=? AND " 126 args = append(args, mtDBTypeToMTType(details.Type)) 127 } 128 129 stmt, err := mtDB.db.Prepare(fmt.Sprintf(`SELECT %s 130 FROM multi_transactions 131 WHERE %s`, 132 selectMultiTransactionColumns, whereClause[:len(whereClause)-5])) 133 if err != nil { 134 return nil, err 135 } 136 defer stmt.Close() 137 138 rows, err := stmt.Query(args...) 139 if err != nil { 140 return nil, err 141 } 142 defer rows.Close() 143 144 return rowsToMultiTransactions(rows) 145 } 146 147 func (mtDB *MultiTransactionDB) UpdateMultiTransaction(multiTransaction *MultiTransaction) error { 148 if multiTransaction.ID == wallet_common.NoMultiTransactionID { 149 return fmt.Errorf("no multitransaction ID") 150 } 151 152 update, err := mtDB.db.Prepare(fmt.Sprintf(`REPLACE INTO multi_transactions (%s) 153 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, multiTransactionColumns)) 154 155 if err != nil { 156 return err 157 } 158 _, err = update.Exec( 159 multiTransaction.ID, 160 multiTransaction.FromNetworkID, 161 multiTransaction.FromTxHash, 162 multiTransaction.FromAddress, 163 multiTransaction.FromAsset, 164 multiTransaction.FromAmount.String(), 165 multiTransaction.ToNetworkID, 166 multiTransaction.ToTxHash, 167 multiTransaction.ToAddress, 168 multiTransaction.ToAsset, 169 multiTransaction.ToAmount.String(), 170 multiTransaction.Type, 171 multiTransaction.CrossTxID, 172 multiTransaction.Timestamp, 173 ) 174 if err != nil { 175 return err 176 } 177 return update.Close() 178 } 179 180 func (mtDB *MultiTransactionDB) DeleteMultiTransaction(id wallet_common.MultiTransactionIDType) error { 181 _, err := mtDB.db.Exec(`DELETE FROM multi_transactions WHERE id=?`, id) 182 return err 183 }