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 Jul 20, 2021
1 parent 51b8c3d commit 223e952
Show file tree
Hide file tree
Showing 9 changed files with 1,002 additions and 21 deletions.
6 changes: 6 additions & 0 deletions client/asset/eth/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import (

"decred.org/dcrdex/client/asset"
"decred.org/dcrdex/dex"
swap "decred.org/dcrdex/dex/networks/eth"
dexeth "decred.org/dcrdex/server/asset/eth"
"github.com/decred/dcrd/dcrutil/v4"
"github.com/ethereum/go-ethereum"
"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 @@ -112,6 +114,7 @@ type ethFetcher interface {
connect(ctx context.Context, node *node.Node, contractAddr common.Address) error
importAccount(pw string, privKeyB []byte) (*accounts.Account, error)
listWallets(ctx context.Context) ([]rawWallet, 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
nodeInfo(ctx context.Context) (*p2p.NodeInfo, error)
pendingTransactions(ctx context.Context) ([]*types.Transaction, error)
Expand All @@ -120,6 +123,9 @@ type ethFetcher interface {
sendTransaction(ctx context.Context, tx map[string]string) (common.Hash, error)
shutdown()
syncProgress(ctx context.Context) (*ethereum.SyncProgress, 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)
swap(ctx context.Context, from *accounts.Account, secretHash [32]byte) (*swap.ETHSwapSwap, 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 @@ -12,9 +12,11 @@ import (
"time"

"decred.org/dcrdex/dex"
swap "decred.org/dcrdex/dex/networks/eth"
dexeth "decred.org/dcrdex/server/asset/eth"
"github.com/ethereum/go-ethereum"
"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 @@ -96,6 +98,18 @@ func (n *testNode) syncProgress(ctx context.Context) (*ethereum.SyncProgress, er
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) (*swap.ETHSwapSwap, error) {
return nil, nil
}
func (n *testNode) transactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
return nil, nil
}
Expand Down
74 changes: 73 additions & 1 deletion client/asset/eth/rpcclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (
"fmt"
"math/big"

swap "decred.org/dcrdex/dex/networks/eth"
"github.com/ethereum/go-ethereum"
"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 @@ -31,18 +33,23 @@ type rpcclient struct {
// ec wraps the client with some useful calls.
ec *ethclient.Client
n *node.Node
es *swap.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 = swap.NewETHSwap(contractAddr, c.ec)
if err != nil {
return fmt.Errorf("unable to find swap contract: %v", err)
}
return nil
}

Expand Down Expand Up @@ -203,3 +210,68 @@ func (c *rpcclient) peers(ctx context.Context) ([]*p2p.PeerInfo, error) {
}
return peers, nil
}

// swap gets a swap keyed by secretHash in the contract.
func (c *rpcclient) swap(ctx context.Context, from *accounts.Account, secretHash [32]byte) (*swap.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
}

// wallet returns a wallet that owns acct from an ethereum wallet.
func (c *rpcclient) wallet(acct accounts.Account) (accounts.Wallet, error) {
wallet, err := c.n.AccountManager().Find(acct)
if err != nil {
return nil, fmt.Errorf("error finding wallet for account %s: %v \n", acct.Address, err)
}
return wallet, 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 matching 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 223e952

Please sign in to comment.