Skip to content

Commit

Permalink
multi: Add ETHSwapV0.
Browse files Browse the repository at this point in the history
Have the eth harness start with a contract. Add contract bindings and
basic calls to clients.
  • Loading branch information
JoeGruffins committed May 5, 2021
1 parent ea51165 commit 1d030df
Show file tree
Hide file tree
Showing 9 changed files with 990 additions and 18 deletions.
5 changes: 5 additions & 0 deletions client/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"decred.org/dcrdex/server/asset/eth"
"github.com/decred/dcrd/dcrutil/v3"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/node"
Expand Down Expand Up @@ -107,13 +108,17 @@ type ethFetcher interface {
blockNumber(ctx context.Context) (uint64, error)
connect(ctx context.Context, node *node.Node, contractAddr common.Address) error
importAccount(pw string, privKeyB []byte) (*accounts.Account, error)
initiate(opts *bind.TransactOpts, netID int64, refundTimestamp int64, secretHash [32]byte, participant common.Address) (*types.Transaction, error)
lock(ctx context.Context, acct *accounts.Account) error
locked(ctx context.Context, acct *accounts.Account) (bool, error)
nodeInfo(ctx context.Context) (*p2p.NodeInfo, error)
pendingTransactions(ctx context.Context) ([]*types.Transaction, error)
transactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
redeem(opts *bind.TransactOpts, netID int64, secret, secretHash [32]byte) (*types.Transaction, error)
refund(opts *bind.TransactOpts, netID int64, secretHash [32]byte) (*types.Transaction, error)
sendToAddr(ctx context.Context, acct *accounts.Account, addr common.Address, amt, gasFee *big.Int) (common.Hash, error)
shutdown()
swap(ctx context.Context, from *accounts.Account, secretHash [32]byte) (*eth.ETHSwapSwap, error)
syncStatus(ctx context.Context) (bool, float32, error)
unlock(ctx context.Context, pw string, acct *accounts.Account) error
}
Expand Down
14 changes: 14 additions & 0 deletions client/asset/eth/eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
"testing"

"decred.org/dcrdex/dex"
"decred.org/dcrdex/server/asset/eth"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/node"
Expand Down Expand Up @@ -77,6 +79,18 @@ func (n *testNode) blockNumber(ctx context.Context) (uint64, error) {
func (n *testNode) pendingTransactions(ctx context.Context) ([]*types.Transaction, error) {
return nil, nil
}
func (n *testNode) initiate(opts *bind.TransactOpts, netID int64, refundTimestamp int64, secretHash [32]byte, participant common.Address) (*types.Transaction, error) {
return nil, nil
}
func (n *testNode) redeem(opts *bind.TransactOpts, netID int64, secret, secretHash [32]byte) (*types.Transaction, error) {
return nil, nil
}
func (n *testNode) refund(opts *bind.TransactOpts, netID int64, secretHash [32]byte) (*types.Transaction, error) {
return nil, nil
}
func (n *testNode) swap(ctx context.Context, from *accounts.Account, secretHash [32]byte) (*eth.ETHSwapSwap, error) {
return nil, nil
}
func (n *testNode) transactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
return nil, nil
}
Expand Down
65 changes: 64 additions & 1 deletion client/asset/eth/rpcclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"fmt"
"math/big"

"decred.org/dcrdex/server/asset/eth"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand All @@ -32,18 +34,23 @@ type rpcclient struct {
// ec wraps the client with some useful calls.
ec *ethclient.Client
n *node.Node
es *eth.ETHSwap
}

// connect connects to a node. It then wraps ethclient's client and
// bundles commands in a form we can easily use.
func (c *rpcclient) connect(ctx context.Context, node *node.Node, contractAddr common.Address) error { // contractAddr will be used soonTM
func (c *rpcclient) connect(ctx context.Context, node *node.Node, contractAddr common.Address) error {
client, err := node.Attach()
if err != nil {
return fmt.Errorf("unable to dial rpc: %v", err)
}
c.c = client
c.ec = ethclient.NewClient(client)
c.n = node
c.es, err = eth.NewETHSwap(contractAddr, c.ec)
if err != nil {
return fmt.Errorf("unable to find swap contract: %v", err)
}
return nil
}

Expand Down Expand Up @@ -245,3 +252,59 @@ func (c *rpcclient) wallet(acct accounts.Account) (accounts.Wallet, error) {
}
return wallet, nil
}

// swap gets a swap keyed by secretHash in the contract.
func (c *rpcclient) swap(ctx context.Context, from *accounts.Account, secretHash [32]byte) (*eth.ETHSwapSwap, error) {
callOpts := &bind.CallOpts{
Pending: true,
From: from.Address,
Context: ctx,
}
swap, err := c.es.Swap(callOpts, secretHash)
if err != nil {
return nil, err
}
return &swap, nil
}

// initiate creates a swap contract. The initiator will be the account at
// txOpts.From. Any on-chain failure, such as this secret hash already existing
// in the swaps map, will not cause this to error.
func (c *rpcclient) initiate(txOpts *bind.TransactOpts, netID int64, refundTimestamp int64, secretHash [32]byte, participant common.Address) (*types.Transaction, error) {
wallet, err := c.wallet(accounts.Account{Address: txOpts.From})
if err != nil {
return nil, err
}
txOpts.Signer = func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return wallet.SignTx(accounts.Account{Address: addr}, tx, big.NewInt(netID))
}
return c.es.Initiate(txOpts, big.NewInt(refundTimestamp), secretHash, participant)
}

// redeem redeems a swap contract. The redeemer will be the account at txOpts.From.
// Any on-chain failure, such as this secret not mathing the hash, will not cause
// this to error.
func (c *rpcclient) redeem(txOpts *bind.TransactOpts, netID int64, secret, secretHash [32]byte) (*types.Transaction, error) {
wallet, err := c.wallet(accounts.Account{Address: txOpts.From})
if err != nil {
return nil, err
}
txOpts.Signer = func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return wallet.SignTx(accounts.Account{Address: addr}, tx, big.NewInt(netID))
}
return c.es.Redeem(txOpts, secret, secretHash)
}

// refund refunds a swap contract. The refunder will be the account at txOpts.From.
// Any on-chain failure, such as the locktime not being past, will not cause
// this to error.
func (c *rpcclient) refund(txOpts *bind.TransactOpts, netID int64, secretHash [32]byte) (*types.Transaction, error) {
wallet, err := c.wallet(accounts.Account{Address: txOpts.From})
if err != nil {
return nil, err
}
txOpts.Signer = func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
return wallet.SignTx(accounts.Account{Address: addr}, tx, big.NewInt(netID))
}
return c.es.Refund(txOpts, secretHash)
}
Loading

0 comments on commit 1d030df

Please sign in to comment.