generated from KyberNetwork/go-project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d20cda0
commit 3235dd2
Showing
10 changed files
with
1,482 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package bebop | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"math/big" | ||
"net/http" | ||
"testing" | ||
"time" | ||
|
||
"github.com/KyberNetwork/tradelogs/pkg/rpcnode" | ||
"github.com/KyberNetwork/tradelogs/pkg/tracecall" | ||
ethereum "github.com/ethereum/go-ethereum" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"github.com/test-go/testify/require" | ||
) | ||
|
||
const rpcURL = "" | ||
|
||
func TestFetchEvent(t *testing.T) { | ||
t.Skip("Need to add the rpc url that enables the trace call JSON-RPC") | ||
rpcClient, err := rpcnode.NewClient(http.DefaultClient, rpcURL) | ||
if err != nil { | ||
panic(err) | ||
} | ||
traceCalls := tracecall.NewCache(rpcClient) | ||
p := MustNewParser(traceCalls) | ||
require.Equal(t, p.abi.Events[TradeEvent].ID, common.HexToHash("0xadd7095becdaa725f0f33243630938c861b0bba83dfd217d4055701aa768ec2e")) | ||
client, err := ethclient.Dial(rpcURL) | ||
require.NoError(t, err) | ||
logs, err := client.FilterLogs(context.Background(), ethereum.FilterQuery{ | ||
BlockHash: nil, | ||
FromBlock: big.NewInt(20009519), | ||
ToBlock: big.NewInt(20009519), | ||
Addresses: nil, | ||
Topics: [][]common.Hash{ | ||
{ | ||
common.HexToHash("0xadd7095becdaa725f0f33243630938c861b0bba83dfd217d4055701aa768ec2e"), | ||
}, | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
d, err := json.Marshal(logs) | ||
require.NoError(t, err) | ||
t.Log(string(d)) | ||
} | ||
|
||
func TestParseEvent(t *testing.T) { | ||
t.Skip("Need to add the rpc url that enables the trace call JSON-RPC") | ||
eventRaw := `[{"address":"0xbbbbbbb520d69a9775e85b458c58c648259fad5f","topics":["0xadd7095becdaa725f0f33243630938c861b0bba83dfd217d4055701aa768ec2e","0x00000000000000000000000000000000bb6e24300f0812800000000000000000"],"data":"0x","blockNumber":"0x131522f","transactionHash":"0x1ced3e62f6e8083901b3d9365947f53edd28cf7901f79b25a9c8161f7b242b2c","transactionIndex":"0x3c","blockHash":"0xc41f37ec02be129d81f9f81527d52b37e00b2368a9ef418eda14f640662a600a","logIndex":"0xe3","removed":false}]` | ||
events := []types.Log{} | ||
err := json.Unmarshal([]byte(eventRaw), &events) | ||
require.NoError(t, err) | ||
rpcClient, err := rpcnode.NewClient(http.DefaultClient, rpcURL) | ||
if err != nil { | ||
panic(err) | ||
} | ||
traceCalls := tracecall.NewCache(rpcClient) | ||
p := MustNewParser(traceCalls) | ||
for _, event := range events { | ||
log, err := p.Parse(event, uint64(time.Now().Unix())) | ||
require.NoError(t, err) | ||
require.Equal(t, log.EventHash, p.eventHash) | ||
t.Log(log.Maker) | ||
t.Log(log.MakerToken) | ||
t.Log(log.MakerTokenAmount) | ||
t.Log(log.Taker) | ||
t.Log(log.TakerToken) | ||
t.Log(log.TakerTokenAmount) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
abigen --abi=abi.json --pkg=bebop --out=bebop.go -type Bebop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
package bebop | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"math/big" | ||
"strings" | ||
|
||
"github.com/KyberNetwork/tradelogs/internal/types" | ||
"github.com/KyberNetwork/tradelogs/pkg/decoder" | ||
"github.com/KyberNetwork/tradelogs/pkg/parser" | ||
"github.com/KyberNetwork/tradelogs/pkg/storage" | ||
"github.com/KyberNetwork/tradelogs/pkg/tracecall" | ||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
"github.com/ethereum/go-ethereum/common" | ||
ethereumTypes "github.com/ethereum/go-ethereum/core/types" | ||
) | ||
|
||
const ( | ||
TradeEvent = "BebopOrder" | ||
OrderParam = "order" | ||
) | ||
|
||
var ( | ||
ErrTradeTopic = errors.New("invalid trade topic") | ||
ErrNotFoundTraceCall = errors.New("not found trace call") | ||
) | ||
|
||
type SingleOrder struct { | ||
Expiry *big.Int `json:"expiry"` | ||
TakerAddress string `json:"taker_address"` | ||
MakerAddress string `json:"maker_address"` | ||
MakerNonce *big.Int `json:"maker_nonce"` | ||
TakerToken string `json:"taker_token"` | ||
MakerToken string `json:"maker_token"` | ||
TakerAmount *big.Int `json:"taker_amount"` | ||
MakerAmount *big.Int `json:"maker_amount"` | ||
Receiver string `json:"receiver"` | ||
PackedCommands *big.Int `json:"packed_commands"` | ||
Flags *big.Int `json:"flags"` | ||
} | ||
|
||
type Parser struct { | ||
abi *abi.ABI | ||
ps *BebopFilterer | ||
eventHash string | ||
traceCalls *tracecall.Cache | ||
} | ||
|
||
func MustNewParser(tracecall *tracecall.Cache) *Parser { | ||
ps, err := NewBebopFilterer(common.Address{}, nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
ab, err := abi.JSON(strings.NewReader(BebopMetaData.ABI)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
event, ok := ab.Events[TradeEvent] | ||
if !ok { | ||
panic("no such event: " + TradeEvent) | ||
} | ||
return &Parser{ | ||
ps: ps, | ||
abi: &ab, | ||
eventHash: event.ID.String(), | ||
traceCalls: tracecall, | ||
} | ||
} | ||
|
||
func (p *Parser) Topics() []string { | ||
return []string{ | ||
p.eventHash, | ||
} | ||
} | ||
|
||
func (p *Parser) Parse(log ethereumTypes.Log, blockTime uint64) (storage.TradeLog, error) { | ||
if len(log.Topics) > 0 && log.Topics[0].Hex() != p.eventHash { | ||
return storage.TradeLog{}, ErrTradeTopic | ||
} | ||
o, err := p.ps.ParseBebopOrder(log) | ||
if err != nil { | ||
return storage.TradeLog{}, err | ||
} | ||
order := storage.TradeLog{ | ||
OrderHash: o.EventId.String(), | ||
Maker: log.Address.Hex(), | ||
ContractAddress: o.Raw.Address.String(), | ||
BlockNumber: o.Raw.BlockNumber, | ||
TxHash: o.Raw.TxHash.String(), | ||
LogIndex: uint64(o.Raw.Index), | ||
Timestamp: blockTime * 1000, | ||
EventHash: p.eventHash, | ||
} | ||
return p.parseTraceCall(order) | ||
} | ||
|
||
func (p *Parser) parseTraceCall(order storage.TradeLog) (storage.TradeLog, error) { | ||
traceCall, err := p.traceCalls.GetTraceCall(order.TxHash) | ||
if err != nil { | ||
return order, err | ||
} | ||
|
||
order, err = p.searchTradeLog(order, traceCall) | ||
if err != nil { | ||
return order, err | ||
} | ||
|
||
return order, nil | ||
} | ||
|
||
func (p *Parser) searchTradeLog(order storage.TradeLog, traceCall types.CallFrame) (storage.TradeLog, error) { | ||
if p.checkBebopTrade(traceCall) { | ||
return p.ParseFromInternalCall(order, traceCall) | ||
} | ||
|
||
for _, subCall := range traceCall.Calls { | ||
tradeLog, err := p.searchTradeLog(order, subCall) | ||
if err == nil { | ||
return tradeLog, nil | ||
} | ||
} | ||
return order, ErrNotFoundTraceCall | ||
} | ||
|
||
func (p *Parser) checkBebopTrade(traceCall types.CallFrame) bool { | ||
for _, eventLog := range traceCall.Logs { | ||
if len(eventLog.Topics) == 0 { | ||
continue | ||
} | ||
if !strings.EqualFold(eventLog.Topics[0].String(), p.eventHash) { | ||
continue | ||
} | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func (p *Parser) ParseFromInternalCall(order storage.TradeLog, internalCall types.CallFrame) (storage.TradeLog, error) { | ||
contractCall, err := decoder.Decode(p.abi, internalCall.Input) | ||
if err != nil { | ||
return order, err | ||
} | ||
|
||
for _, param := range contractCall.Params { | ||
if param.Name != OrderParam { | ||
continue | ||
} | ||
var rfqOrder SingleOrder | ||
bytes, err := json.Marshal(param.Value) | ||
if err != nil { | ||
return order, err | ||
} | ||
|
||
if err := json.Unmarshal(bytes, &rfqOrder); err != nil { | ||
return order, err | ||
} | ||
order.MakerToken = rfqOrder.MakerToken | ||
order.TakerToken = rfqOrder.TakerToken | ||
order.Maker = rfqOrder.MakerAddress | ||
order.Taker = rfqOrder.TakerAddress | ||
order.MakerTokenAmount = rfqOrder.MakerAmount.String() | ||
order.TakerTokenAmount = rfqOrder.TakerAmount.String() | ||
} | ||
|
||
return order, nil | ||
} | ||
|
||
func (p *Parser) Exchange() string { | ||
return parser.ExBebop | ||
} | ||
|
||
func (p *Parser) UseTraceCall() bool { | ||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters