From 4fd460ca3c0d202f20707c5ebb27930a46d5bc3b Mon Sep 17 00:00:00 2001 From: iostream1308 <51293334+iostream1308@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:57:40 +0700 Subject: [PATCH] add exclusive order data (#122) * add exclusive order data * add tradelog mview * fix lint * add worker for refresh * add worker for refresh * add worker for refresh --- .../00017_add_exclusive_order_data.up.sql | 311 ++++++++++++++++++ v2/cmd/tradelogs/main.go | 3 + v2/internal/worker/mview_refresher.go | 37 +++ v2/pkg/parser/uniswapx/parser.go | 9 + v2/pkg/storage/dashboard/storage.go | 5 + .../storage/tradelogs/pancakeswap/storage.go | 85 ++++- v2/pkg/storage/tradelogs/types/trade_log.go | 3 + v2/pkg/storage/tradelogs/uniswapx/storage.go | 94 +++++- 8 files changed, 537 insertions(+), 10 deletions(-) create mode 100644 v2/cmd/migrations/00017_add_exclusive_order_data.up.sql create mode 100644 v2/internal/worker/mview_refresher.go diff --git a/v2/cmd/migrations/00017_add_exclusive_order_data.up.sql b/v2/cmd/migrations/00017_add_exclusive_order_data.up.sql new file mode 100644 index 0000000..9a91b8a --- /dev/null +++ b/v2/cmd/migrations/00017_add_exclusive_order_data.up.sql @@ -0,0 +1,311 @@ +ALTER TABLE tradelogs_uniswapx +ADD COLUMN expiration BIGINT NOT NULL DEFAULT 0, +ADD COLUMN decay_start_time BIGINT DEFAULT NULL, +ADD COLUMN decay_end_time BIGINT DEFAULT NULL, +ADD COLUMN exclusive_filler TEXT NOT NULL DEFAULT ''; + +ALTER TABLE tradelogs_pancakeswap +ADD COLUMN expiration BIGINT NOT NULL DEFAULT 0; + +CREATE MATERIALIZED VIEW mview_tradelogs AS +WITH all_trades AS ( + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'zerox' AS contract, + '' AS type + FROM public.tradelogs_zerox + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'kyberswap' AS contract, + '' AS type + FROM public.tradelogs_kyberswap + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'kyberswap_rfq' AS contract, + '' AS type + FROM public.tradelogs_kyberswap_rfq + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'paraswap' AS contract, + '' AS type + FROM public.tradelogs_paraswap + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'hashflow_v3' AS contract, + '' AS type + FROM public.tradelogs_hashflow_v3 + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'oneinch_v6' AS contract, + type + FROM public.tradelogs_oneinch_v6 + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'uniswapx' AS contract, + '' AS type + FROM public.tradelogs_uniswapx + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'bebop' AS contract, + '' AS type + FROM public.tradelogs_bebop + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'zerox_v3' AS contract, + '' AS type + FROM public.tradelogs_zerox_v3 + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 + + UNION ALL + + SELECT + maker, + taker, + maker_token, + taker_token, + CASE + WHEN maker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(maker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS maker_token_amount, + CASE + WHEN taker_token_amount ~ '^[0-9]+(\.[0-9]+)?$' THEN REPLACE(taker_token_amount, ',', '.')::DECIMAL + ELSE NULL + END AS taker_token_amount, + contract_address, + block_number, + tx_hash, + timestamp, + event_hash, + maker_token_price, + taker_token_price, + maker_usd_amount, + taker_usd_amount, + 'pancakeswap' AS contract, + '' AS type + FROM public.tradelogs_pancakeswap + WHERE timestamp >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - INTERVAL '3 months') * 1000 + AND maker_usd_amount > 0 AND taker_usd_amount > 0 +) +SELECT * FROM all_trades ORDER BY timestamp DESC; diff --git a/v2/cmd/tradelogs/main.go b/v2/cmd/tradelogs/main.go index 395d284..b3ad7ff 100644 --- a/v2/cmd/tradelogs/main.go +++ b/v2/cmd/tradelogs/main.go @@ -6,6 +6,7 @@ import ( "os" "github.com/KyberNetwork/tradelogs/v2/internal/server" + "github.com/KyberNetwork/tradelogs/v2/internal/worker" libapp "github.com/KyberNetwork/tradelogs/v2/pkg/app" dashboardStorage "github.com/KyberNetwork/tradelogs/v2/pkg/storage/dashboard" bebopStorage "github.com/KyberNetwork/tradelogs/v2/pkg/storage/tradelogs/bebop" @@ -69,6 +70,8 @@ func run(c *cli.Context) error { pancakeswapStorage.New(l, db), } dashStorage := dashboardStorage.New(l, db) + mviewRefresher := worker.NewRefresher(dashStorage, l) + mviewRefresher.Run() s := server.NewTradeLogs(l, storage, dashStorage, c.String(libapp.HTTPTradeLogsServerFlag.Name)) return s.Run() } diff --git a/v2/internal/worker/mview_refresher.go b/v2/internal/worker/mview_refresher.go new file mode 100644 index 0000000..86be801 --- /dev/null +++ b/v2/internal/worker/mview_refresher.go @@ -0,0 +1,37 @@ +package worker + +import ( + "time" + + dashboardStorage "github.com/KyberNetwork/tradelogs/v2/pkg/storage/dashboard" + "go.uber.org/zap" +) + +type Refresher struct { + DashStorage *dashboardStorage.Storage + l *zap.SugaredLogger +} + +func NewRefresher(dashStorage *dashboardStorage.Storage, l *zap.SugaredLogger) *Refresher { + return &Refresher{ + DashStorage: dashStorage, + l: l, + } +} + +func (r *Refresher) Run() { + go r.ScheduleMViewRefresh() +} + +func (r *Refresher) ScheduleMViewRefresh() { + ticker := time.NewTicker(24 * time.Hour) + defer ticker.Stop() + for range ticker.C { + err := r.DashStorage.RefreshTradelogsMView() + if err != nil { + r.l.Errorf("Error refreshing materialized view: %v", err) + } else { + r.l.Info("Materialized view refreshed successfully.") + } + } +} diff --git a/v2/pkg/parser/uniswapx/parser.go b/v2/pkg/parser/uniswapx/parser.go index 10eed41..342ff1f 100644 --- a/v2/pkg/parser/uniswapx/parser.go +++ b/v2/pkg/parser/uniswapx/parser.go @@ -249,6 +249,15 @@ func (p *Parser) updateOrder(tradeLog storageTypes.TradeLog, call types.CallFram if order.Info.Deadline != nil { tradeLog.Expiry = order.Info.Deadline.Uint64() } + if order.CosignerData.DecayStartTime != nil { + var decayStartTime uint64 = order.CosignerData.DecayStartTime.Uint64() + tradeLog.DecayStartTime = &decayStartTime + } + if order.CosignerData.DecayEndTime != nil { + var decayEndTime uint64 = order.CosignerData.DecayEndTime.Uint64() + tradeLog.DecayEndTime = &decayEndTime + } + tradeLog.ExclusiveFiller = order.CosignerData.ExclusiveFiller.Hex() return tradeLog, nil } diff --git a/v2/pkg/storage/dashboard/storage.go b/v2/pkg/storage/dashboard/storage.go index ee2813f..979db28 100644 --- a/v2/pkg/storage/dashboard/storage.go +++ b/v2/pkg/storage/dashboard/storage.go @@ -196,3 +196,8 @@ func (s *Storage) GetTxOrigin(query types.TxOriginQuery) ([]types.TxOrigin, erro return txOrigins, nil } + +func (s *Storage) RefreshTradelogsMView() error { + _, err := s.db.Exec("REFRESH MATERIALIZED VIEW mview_tradelogs WITH DATA") + return err +} diff --git a/v2/pkg/storage/tradelogs/pancakeswap/storage.go b/v2/pkg/storage/tradelogs/pancakeswap/storage.go index 4bbd427..c76eacb 100644 --- a/v2/pkg/storage/tradelogs/pancakeswap/storage.go +++ b/v2/pkg/storage/tradelogs/pancakeswap/storage.go @@ -37,14 +37,37 @@ func (s *Storage) Insert(orders []storageTypes.TradeLog) error { return nil } b := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(s.tableName()).Columns( - storageTypes.CommonTradeLogColumns()..., + tradeLogColumns()..., ) for _, order := range orders { b = b.Values( - storageTypes.CommonTradeLogSerialize(&order)..., + tradeLogSerialize(&order)..., ) } - q, p, err := b.Suffix(storageTypes.CommonTradeLogSuffix()).ToSql() + q, p, err := b.Suffix(`ON CONFLICT(block_number, log_index) DO UPDATE + SET + order_hash=excluded.order_hash, + maker=excluded.maker, + taker=excluded.taker, + maker_token=excluded.maker_token, + taker_token=excluded.taker_token, + maker_token_amount=excluded.maker_token_amount, + taker_token_amount=excluded.taker_token_amount, + contract_address=excluded.contract_address, + block_number=excluded.block_number, + tx_hash=excluded.tx_hash, + log_index=excluded.log_index, + timestamp=excluded.timestamp, + event_hash=excluded.event_hash, + tx_origin=excluded.tx_origin, + message_sender=excluded.message_sender, + interact_contract=excluded.interact_contract, + maker_token_price=excluded.maker_token_price, + taker_token_price=excluded.taker_token_price, + maker_usd_amount=excluded.maker_usd_amount, + taker_usd_amount=excluded.taker_usd_amount, + expiration=excluded.expiration + `).ToSql() if err != nil { s.l.Errorw("Error build insert", "error", err) return err @@ -58,7 +81,7 @@ func (s *Storage) Insert(orders []storageTypes.TradeLog) error { func (s *Storage) Get(query storageTypes.TradeLogsQuery) ([]storageTypes.TradeLog, error) { builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). - Select(storageTypes.CommonTradeLogColumns()...). + Select(tradeLogColumns()...). From(s.tableName()) if query.FromTime != 0 { builder = builder.Where(squirrel.GtOrEq{"timestamp": query.FromTime}) @@ -97,7 +120,7 @@ func (s *Storage) Get(query storageTypes.TradeLogsQuery) ([]storageTypes.TradeLo func (s *Storage) GetEmptyPrice(limit uint64) ([]storageTypes.TradeLog, error) { builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). - Select(storageTypes.CommonTradeLogColumns()...). + Select(tradeLogColumns()...). From(s.tableName()).Where(squirrel.Eq{"maker_token_price": nil}).Limit(limit) q, p, err := builder.ToSql() if err != nil { @@ -161,3 +184,55 @@ func (s *Storage) ResetTokenPriceToRefetch(token string, from, to int64) (int64, } return rowsAffected, nil } + +func tradeLogSerialize(o *storageTypes.TradeLog) []interface{} { + return []interface{}{ + o.OrderHash, + strings.ToLower(o.Maker), + strings.ToLower(o.Taker), + strings.ToLower(o.MakerToken), + strings.ToLower(o.TakerToken), + o.MakerTokenAmount, + o.TakerTokenAmount, + strings.ToLower(o.ContractAddress), + o.BlockNumber, + o.TxHash, + o.LogIndex, + o.Timestamp, + o.EventHash, + o.TxOrigin, + o.MessageSender, + o.InteractContract, + o.MakerTokenPrice, + o.TakerTokenPrice, + o.MakerUsdAmount, + o.TakerUsdAmount, + o.Expiry, + } +} + +func tradeLogColumns() []string { + return []string{ + "order_hash", + "maker", + "taker", + "maker_token", + "taker_token", + "maker_token_amount", + "taker_token_amount", + "contract_address", + "block_number", + "tx_hash", + "log_index", + "timestamp", + "event_hash", + "tx_origin", + "message_sender", + "interact_contract", + "maker_token_price", + "taker_token_price", + "maker_usd_amount", + "taker_usd_amount", + "expiration", + } +} diff --git a/v2/pkg/storage/tradelogs/types/trade_log.go b/v2/pkg/storage/tradelogs/types/trade_log.go index 2f5e63c..2bd85fb 100644 --- a/v2/pkg/storage/tradelogs/types/trade_log.go +++ b/v2/pkg/storage/tradelogs/types/trade_log.go @@ -33,6 +33,9 @@ type TradeLog struct { MakerUsdAmount *float64 `db:"maker_usd_amount" json:"maker_usd_amount"` TakerUsdAmount *float64 `db:"taker_usd_amount" json:"taker_usd_amount"` Type OneInchType `db:"type" json:"type,omitempty"` + DecayStartTime *uint64 `db:"decay_start_time" json:"decay_start_time,omitempty"` + DecayEndTime *uint64 `db:"decay_end_time" json:"decay_end_time,omitempty"` + ExclusiveFiller string `db:"exclusive_filler" json:"exclusive_filler,omitempty"` } // CommonTradeLogSerialize used for exchanges only storing fields in common trade logs, diff --git a/v2/pkg/storage/tradelogs/uniswapx/storage.go b/v2/pkg/storage/tradelogs/uniswapx/storage.go index d9c6938..202a18d 100644 --- a/v2/pkg/storage/tradelogs/uniswapx/storage.go +++ b/v2/pkg/storage/tradelogs/uniswapx/storage.go @@ -37,14 +37,40 @@ func (s *Storage) Insert(orders []storageTypes.TradeLog) error { return nil } b := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(s.tableName()).Columns( - storageTypes.CommonTradeLogColumns()..., + tradeLogColumns()..., ) for _, order := range orders { b = b.Values( - storageTypes.CommonTradeLogSerialize(&order)..., + tradeLogSerialize(&order)..., ) } - q, p, err := b.Suffix(storageTypes.CommonTradeLogSuffix()).ToSql() + q, p, err := b.Suffix(`ON CONFLICT(block_number, log_index) DO UPDATE + SET + order_hash=excluded.order_hash, + maker=excluded.maker, + taker=excluded.taker, + maker_token=excluded.maker_token, + taker_token=excluded.taker_token, + maker_token_amount=excluded.maker_token_amount, + taker_token_amount=excluded.taker_token_amount, + contract_address=excluded.contract_address, + block_number=excluded.block_number, + tx_hash=excluded.tx_hash, + log_index=excluded.log_index, + timestamp=excluded.timestamp, + event_hash=excluded.event_hash, + tx_origin=excluded.tx_origin, + message_sender=excluded.message_sender, + interact_contract=excluded.interact_contract, + maker_token_price=excluded.maker_token_price, + taker_token_price=excluded.taker_token_price, + maker_usd_amount=excluded.maker_usd_amount, + taker_usd_amount=excluded.taker_usd_amount, + expiration=excluded.expiration, + decay_start_time=excluded.decay_start_time, + decay_end_time=excluded.decay_end_time, + exclusive_filler=excluded.exclusive_filler + `).ToSql() if err != nil { s.l.Errorw("Error build insert", "error", err) return err @@ -58,7 +84,7 @@ func (s *Storage) Insert(orders []storageTypes.TradeLog) error { func (s *Storage) Get(query storageTypes.TradeLogsQuery) ([]storageTypes.TradeLog, error) { builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). - Select(storageTypes.CommonTradeLogColumns()...). + Select(tradeLogColumns()...). From(s.tableName()) if query.FromTime != 0 { builder = builder.Where(squirrel.GtOrEq{"timestamp": query.FromTime}) @@ -97,7 +123,7 @@ func (s *Storage) Get(query storageTypes.TradeLogsQuery) ([]storageTypes.TradeLo func (s *Storage) GetEmptyPrice(limit uint64) ([]storageTypes.TradeLog, error) { builder := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar). - Select(storageTypes.CommonTradeLogColumns()...). + Select(tradeLogColumns()...). From(s.tableName()).Where(squirrel.Eq{"maker_token_price": nil}).Limit(limit) q, p, err := builder.ToSql() if err != nil { @@ -161,3 +187,61 @@ func (s *Storage) ResetTokenPriceToRefetch(token string, from, to int64) (int64, } return rowsAffected, nil } + +func tradeLogSerialize(o *storageTypes.TradeLog) []interface{} { + return []interface{}{ + o.OrderHash, + strings.ToLower(o.Maker), + strings.ToLower(o.Taker), + strings.ToLower(o.MakerToken), + strings.ToLower(o.TakerToken), + o.MakerTokenAmount, + o.TakerTokenAmount, + strings.ToLower(o.ContractAddress), + o.BlockNumber, + o.TxHash, + o.LogIndex, + o.Timestamp, + o.EventHash, + o.TxOrigin, + o.MessageSender, + o.InteractContract, + o.MakerTokenPrice, + o.TakerTokenPrice, + o.MakerUsdAmount, + o.TakerUsdAmount, + o.Expiry, + o.DecayStartTime, + o.DecayEndTime, + strings.ToLower(o.ExclusiveFiller), + } +} + +func tradeLogColumns() []string { + return []string{ + "order_hash", + "maker", + "taker", + "maker_token", + "taker_token", + "maker_token_amount", + "taker_token_amount", + "contract_address", + "block_number", + "tx_hash", + "log_index", + "timestamp", + "event_hash", + "tx_origin", + "message_sender", + "interact_contract", + "maker_token_price", + "taker_token_price", + "maker_usd_amount", + "taker_usd_amount", + "expiration", + "decay_start_time", + "decay_end_time", + "exclusive_filler", + } +}