This repository has been archived by the owner on Aug 21, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 56
/
pool.go
166 lines (153 loc) · 4.86 KB
/
pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package pool
import (
"bytes"
"net/http"
"github.com/notegio/openrelay/config"
dbModule "github.com/notegio/openrelay/db"
"github.com/notegio/openrelay/types"
"github.com/notegio/openrelay/search"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/jinzhu/gorm"
"github.com/ethereum/go-ethereum/crypto/sha3"
"gopkg.in/redis.v3"
"math/big"
urlModule "net/url"
"regexp"
"strings"
"fmt"
)
var feeBaseUnits = big.NewInt(1000000000000000000)
type Pool struct {
SearchTerms string
Expiration uint64
Nonce uint
FeeShare string
ID []byte
Limit uint
SenderAddresses types.NetworkAddressMap
FilterAddresses types.NetworkAddressMap
conn bind.ContractCaller
baseFee config.BaseFee
}
func (pool *Pool) SetConn(conn bind.ContractCaller) {
pool.conn = conn
}
func (pool *Pool) SetBaseFee(baseFee config.BaseFee) {
pool.baseFee = baseFee
}
func (pool *Pool) CheckFilter(order *types.Order, networkid uint) (bool, error) {
if len(pool.FilterAddresses) == 0 {
return true, nil
}
filterAddress, ok := pool.FilterAddresses[networkid]
if !ok {
// networkid is not supported by this pool, so neither is this order
return false, nil
}
if bytes.Equal(filterAddress[:], make([]byte, 20)) {
// If no filter contract is specified, everything is valid
return true, nil
}
if pool.conn == nil {
return false, fmt.Errorf("No connection set on pool")
}
return NewFilterContract(filterAddress, pool.conn).Filter(pool.ID, order)
}
func (pool Pool) Filter(query *gorm.DB) (*gorm.DB, error) {
queryObject, err := urlModule.ParseQuery(pool.SearchTerms)
if err != nil {
return nil, err
}
query, errs := search.QueryFilter(query, queryObject)
if errCount := len(errs); errCount > 0 {
return nil, fmt.Errorf("Found %v errors in pool query string", errCount)
}
return query, nil
}
func (pool Pool) Count(db *gorm.DB) (<-chan uint) {
result := make(chan uint)
var value uint
go func() {
db.Model(&dbModule.Order{}).Where("pool_id = ?", pool.ID).Where("status = ?", dbModule.StatusOpen).Count(&value)
result <- value
}()
return result
}
func (pool Pool) Fee() (*big.Int, error) {
baseFee, err := pool.baseFee.Get()
if err != nil {
return nil, err
}
feeShare := new(big.Int)
if _, ok := feeShare.SetString(pool.FeeShare, 10); !ok {
// If the fee share is not a valid integer, just return the base fee
return baseFee, nil
}
combined := new(big.Int).Mul(baseFee, feeShare)
return new(big.Int).Div(combined, feeBaseUnits), nil
}
func (pool Pool) QueryString() string {
return pool.SearchTerms
}
var poolRegex = regexp.MustCompile("^(/[^/]*)?/v2/")
func PoolDecorator(db *gorm.DB, fn func(http.ResponseWriter, *http.Request, types.Pool)) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
match := poolRegex.FindStringSubmatch(r.URL.Path)
if len(match) == 2 {
poolName := strings.TrimPrefix(match[1], "/")
pool := &Pool{}
poolHash := sha3.NewKeccak256()
poolHash.Write([]byte(poolName))
if db != nil {
if q := db.Model(&Pool{}).Where("ID = ?", poolHash.Sum(nil)).First(pool); q.Error != nil {
if poolName != "" {
w.WriteHeader(404)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(fmt.Sprintf("{\"code\":102,\"reason\":\"Pool Not Found: %v\"}", q.Error.Error())))
return
}
// If no pool was specified and no default pool is in the database,
// just use an empty pool
}
}
fn(w, r, pool)
} else {
// Routing regex shouldn't get here
w.WriteHeader(404)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(fmt.Sprintf("{\"code\":102,\"reason\":\"Not Found\"}")))
return
}
}
}
func PoolDecoratorBaseFee(db *gorm.DB, redisClient *redis.Client, fn func(http.ResponseWriter, *http.Request, *Pool)) func(http.ResponseWriter, *http.Request) {
baseFee := config.NewBaseFee(redisClient)
return func(w http.ResponseWriter, r *http.Request) {
match := poolRegex.FindStringSubmatch(r.URL.Path)
if len(match) == 2 {
poolName := strings.TrimPrefix(match[1], "/")
pool := &Pool{}
poolHash := sha3.NewKeccak256()
poolHash.Write([]byte(poolName))
if q := db.Model(&Pool{}).Where("ID = ?", poolHash.Sum(nil)).First(pool); q.Error != nil {
if poolName != "" {
w.WriteHeader(404)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(fmt.Sprintf("{\"code\":102,\"reason\":\"Pool Not Found: %v\"}", q.Error.Error())))
return
}
// If no pool was specified and no default pool is in the database,
// just use an empty pool
}
pool.baseFee = baseFee
fmt.Printf("Pool: %v", pool)
fn(w, r, pool)
} else {
// Routing regex shouldn't get here
w.WriteHeader(404)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(fmt.Sprintf("{\"code\":102,\"reason\":\"Not Found\"}")))
return
}
}
}