-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add pairs #495
add pairs #495
Changes from 8 commits
be99723
450535c
2d8e096
3dfaa9d
b1caca7
bdfd3e6
c2a7940
64c92fd
0ed0371
12b5ae7
4d475e2
78b6cac
8f93cb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright 2023 The AthanorLabs/atomic-swap Authors | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
package types | ||
|
||
import ( | ||
"github.com/cockroachdb/apd/v3" | ||
|
||
"github.com/athanorlabs/atomic-swap/coins" | ||
) | ||
|
||
// Pair represents a pair (Such as ETH / XMR) | ||
type Pair struct { | ||
ReportedLiquidityXMR *apd.Decimal `json:"reportedLiquidityXmr" validate:"required"` | ||
EthAsset EthAsset `json:"ethAsset" validate:"required"` | ||
Token coins.ERC20TokenInfo `json:"token" validate:"required"` | ||
Offers uint64 `json:"offers" validate:"required"` | ||
Verified bool `json:"verified" valdate:"required"` | ||
} | ||
|
||
// NewPair creates and returns a Pair | ||
func NewPair(EthAsset EthAsset) *Pair { | ||
pair := &Pair{ | ||
ReportedLiquidityXMR: apd.New(0, 0), | ||
EthAsset: EthAsset, | ||
|
||
// Always set to false for now until the verified-list | ||
// is implemented | ||
Verified: false, | ||
} | ||
return pair | ||
} | ||
|
||
// AddOffer adds an offer to a pair | ||
func (pair *Pair) AddOffer(o *Offer) error { | ||
_, err := coins.DecimalCtx().Add(pair.ReportedLiquidityXMR, pair.ReportedLiquidityXMR, o.MaxAmount) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pair.Offers++ | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
package rpc | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
@@ -18,6 +19,8 @@ import ( | |
"github.com/athanorlabs/atomic-swap/common/types" | ||
"github.com/athanorlabs/atomic-swap/net/message" | ||
"github.com/athanorlabs/atomic-swap/protocol/swap" | ||
|
||
ethcommon "github.com/ethereum/go-ethereum/common" | ||
) | ||
|
||
const defaultSearchTime = time.Second * 12 | ||
|
@@ -35,19 +38,31 @@ type Net interface { | |
|
||
// NetService is the RPC service prefixed by net_. | ||
type NetService struct { | ||
ctx context.Context | ||
net Net | ||
xmrtaker XMRTaker | ||
xmrmaker XMRMaker | ||
pb ProtocolBackend | ||
sm swap.Manager | ||
isBootnode bool | ||
} | ||
|
||
// NewNetService ... | ||
func NewNetService(net Net, xmrtaker XMRTaker, xmrmaker XMRMaker, sm swap.Manager, isBootnode bool) *NetService { | ||
func NewNetService( | ||
ctx context.Context, | ||
net Net, | ||
xmrtaker XMRTaker, | ||
xmrmaker XMRMaker, | ||
pb ProtocolBackend, | ||
sm swap.Manager, | ||
isBootnode bool, | ||
) *NetService { | ||
return &NetService{ | ||
ctx: ctx, | ||
net: net, | ||
xmrtaker: xmrtaker, | ||
xmrmaker: xmrmaker, | ||
pb: pb, | ||
sm: sm, | ||
isBootnode: isBootnode, | ||
} | ||
|
@@ -73,6 +88,71 @@ func (s *NetService) Peers(_ *http.Request, _ *interface{}, resp *rpctypes.Peers | |
return nil | ||
} | ||
|
||
// Pairs returns all currently available pairs from offers of all peers | ||
func (s *NetService) Pairs(_ *http.Request, req *rpctypes.PairsRequest, resp *rpctypes.PairsResponse) error { | ||
if s.isBootnode { | ||
return errUnsupportedForBootnode | ||
} | ||
|
||
peerIDs, err := s.discover(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
addrs := make(map[ethcommon.Address]int) | ||
pairs := make([]*types.Pair, 0, 100) | ||
|
||
addrs[ethcommon.Address{}] = 0 // ETH/XMR pair is always first | ||
pairs = append(pairs, types.NewPair(types.EthAsset{})) | ||
pairs[0].Verified = true | ||
pairs[0].Token = coins.ERC20TokenInfo{ | ||
NumDecimals: 18, | ||
Name: "Ether", | ||
Symbol: "ETH", | ||
} | ||
|
||
for _, p := range peerIDs { | ||
msg, err := s.net.Query(p) | ||
if err != nil { | ||
log.Debugf("Failed to query peer ID %s", p) | ||
continue | ||
} | ||
if len(msg.Offers) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit for readability, but can you change this to:
|
||
for _, o := range msg.Offers { | ||
address := o.EthAsset.Address() | ||
index, exists := addrs[address] | ||
pair := types.NewPair(o.EthAsset) | ||
if !exists { | ||
addrs[address] = index | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the value does not exist in the map, isn't |
||
if pair.EthAsset.IsToken() { | ||
tokenInfo, tokenInfoErr := s.pb.ETHClient().ERC20Info(s.ctx, address) | ||
if tokenInfoErr != nil { | ||
log.Debugf("Error while reading token info: %s", tokenInfoErr) | ||
continue | ||
} | ||
pair.Token = *tokenInfo | ||
} | ||
pairs = append(pairs, pair) | ||
} else { | ||
pair = pairs[index] | ||
} | ||
err = pair.AddOffer(o) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Remove ETH/XMR pair if there is no offer | ||
if pairs[0].Offers <= 0 { | ||
pairs = pairs[1:] | ||
} | ||
|
||
resp.Pairs = pairs | ||
return nil | ||
} | ||
|
||
// QueryAll discovers peers who provide a certain coin and queries all of them for their current offers. | ||
func (s *NetService) QueryAll(_ *http.Request, req *rpctypes.QueryAllRequest, resp *rpctypes.QueryAllResponse) error { | ||
if s.isBootnode { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2023 The AthanorLabs/atomic-swap Authors | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
package rpcclient | ||
|
||
import ( | ||
"github.com/athanorlabs/atomic-swap/common/rpctypes" | ||
) | ||
|
||
// Pairs calls net_pairs to get pairs from all offers. | ||
func (c *Client) Pairs(searchTime uint64) (*rpctypes.PairsResponse, error) { | ||
const ( | ||
method = "net_pairs" | ||
) | ||
|
||
req := &rpctypes.PairsRequest{ | ||
Provides: "", | ||
SearchTime: searchTime, | ||
} | ||
|
||
res := &rpctypes.PairsResponse{} | ||
|
||
if err := c.post(method, req, res); err != nil { | ||
return nil, err | ||
} | ||
|
||
return res, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.DS_Store | ||
node_modules | ||
/build | ||
/.svelte-kit | ||
/package | ||
.env | ||
.env.* | ||
!.env.example | ||
|
||
# Ignore files for PNPM, NPM and YARN | ||
pnpm-lock.yaml | ||
package-lock.json | ||
yarn.lock |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"useTabs": true, | ||
"singleQuote": true, | ||
"trailingComma": "none", | ||
"printWidth": 100, | ||
"plugins": ["prettier-plugin-svelte"], | ||
"pluginSearchDirs": ["."], | ||
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the
Provides
field of the request is always set to""
, can you define this as a new type: