Files
atomic-swap/rpc/server.go
2022-06-13 20:50:10 -04:00

143 lines
3.9 KiB
Go

package rpc
import (
"context"
"fmt"
"net/http"
"time"
"github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/common/types"
mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/protocol/swap"
"github.com/noot/atomic-swap/protocol/txsender"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/gorilla/rpc/v2"
logging "github.com/ipfs/go-log"
)
var log = logging.Logger("rpc")
// Server represents the JSON-RPC server
type Server struct {
s *rpc.Server
wsServer *wsServer
port uint16
wsPort uint16
}
// Config ...
type Config struct {
Ctx context.Context
Port uint16
WsPort uint16
Net Net
XMRTaker XMRTaker
XMRMaker XMRMaker
ProtocolBackend ProtocolBackend
}
// NewServer ...
func NewServer(cfg *Config) (*Server, error) {
s := rpc.NewServer()
s.RegisterCodec(NewCodec(), "application/json")
ns := NewNetService(cfg.Net, cfg.XMRTaker, cfg.XMRMaker, cfg.ProtocolBackend.SwapManager())
if err := s.RegisterService(ns, "net"); err != nil {
return nil, err
}
if err := s.RegisterService(NewPersonalService(cfg.XMRMaker, cfg.ProtocolBackend), "personal"); err != nil {
return nil, err
}
if err := s.RegisterService(NewSwapService(cfg.ProtocolBackend.SwapManager(), cfg.XMRTaker, cfg.XMRMaker, cfg.Net), "swap"); err != nil { //nolint:lll
return nil, err
}
return &Server{
s: s,
wsServer: newWsServer(cfg.Ctx, cfg.ProtocolBackend.SwapManager(), ns, cfg.ProtocolBackend, cfg.ProtocolBackend.ExternalSender()), //nolint:lll
port: cfg.Port,
wsPort: cfg.WsPort,
}, nil
}
// Start starts the JSON-RPC server.
func (s *Server) Start() <-chan error {
errCh := make(chan error)
go func() {
r := mux.NewRouter()
r.Handle("/", s.s)
headersOk := handlers.AllowedHeaders([]string{"content-type", "username", "password"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
originsOk := handlers.AllowedOrigins([]string{"*"})
log.Infof("starting RPC server on http://localhost:%d", s.port)
if err := http.ListenAndServe(fmt.Sprintf(":%d", s.port), handlers.CORS(headersOk, methodsOk, originsOk)(r)); err != nil { //nolint:lll
log.Errorf("failed to start http RPC server: %s", err)
errCh <- err
}
}()
go func() {
r := mux.NewRouter()
r.Handle("/", s.wsServer)
headersOk := handlers.AllowedHeaders([]string{"content-type", "username", "password"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
originsOk := handlers.AllowedOrigins([]string{"*"})
log.Infof("starting websockets server on ws://localhost:%d", s.wsPort)
if err := http.ListenAndServe(fmt.Sprintf(":%d", s.wsPort), handlers.CORS(headersOk, methodsOk, originsOk)(r)); err != nil { //nolint:lll
log.Errorf("failed to start websockets RPC server: %s", err)
errCh <- err
}
}()
return errCh
}
// Protocol represents the functions required by the rpc service into the protocol handler.
type Protocol interface {
Provides() types.ProvidesCoin
GetOngoingSwapState(types.Hash) common.SwapState
}
// ProtocolBackend represents protocol/backend.Backend
type ProtocolBackend interface {
SetGasPrice(uint64)
SetSwapTimeout(timeout time.Duration)
SwapManager() swap.Manager
ExternalSender() *txsender.ExternalSender
SetEthAddress(ethcommon.Address)
SetXMRDepositAddress(mcrypto.Address, types.Hash)
}
// XMRTaker ...
type XMRTaker interface {
Protocol
InitiateProtocol(providesAmount float64, offer *types.Offer) (common.SwapState, error)
Refund(types.Hash) (ethcommon.Hash, error)
}
// XMRMaker ...
type XMRMaker interface {
Protocol
MakeOffer(offer *types.Offer) (*types.OfferExtra, error)
SetMoneroWalletFile(file, password string) error
GetOffers() []*types.Offer
ClearOffers()
}
// SwapManager ...
type SwapManager = swap.Manager