Skip to content

Commit

Permalink
dcr: Add send all.
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeGruffins committed Jan 7, 2025
1 parent 10344df commit 8b3c431
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 18 deletions.
67 changes: 51 additions & 16 deletions asset/dcr/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math"
"math/rand"

dexdcr "decred.org/dcrdex/dex/networks/dcr"
wallettypes "decred.org/dcrwallet/v4/rpc/jsonrpc/types"
"decred.org/dcrwallet/v4/wallet"
"decred.org/dcrwallet/v4/wallet/txauthor"
Expand Down Expand Up @@ -62,19 +63,32 @@ func (in Input) String() string {
}

// CreateSignedTransaction creates a signed transaction. The wallet must be
// unlocked before calling.
func (w *Wallet) CreateSignedTransaction(ctx context.Context, outputs []*Output, inputs, ignoreInputs []*Input, feeRate uint64) (signedTx []byte, txid *chainhash.Hash, fee uint64, err error) {
// unlocked before calling. sendAll will send everything to one output. In that
// case the output's amount is ignored.
func (w *Wallet) CreateSignedTransaction(ctx context.Context, outputs []*Output,
inputs, ignoreInputs []*Input, feeRate uint64, sendAll bool) (signedTx []byte,
txid *chainhash.Hash, fee uint64, err error) {
if sendAll && len(outputs) > 1 {
return nil, nil, 0, errors.New("send all can only be used with one recepient")
}
if len(outputs) < 1 {
return nil, nil, 0, errors.New("no outputs")
}
var ignoreCoinIDs = make(map[string]struct{})
for _, in := range ignoreInputs {
ignoreCoinIDs[in.String()] = struct{}{}
}
var inputSource txauthor.InputSource
var (
inputSource txauthor.InputSource
totalIn uint64
)
details := new(txauthor.InputDetail)
addUTXO := func(utxo *wallettypes.ListUnspentResult, coinID string) error {
amt, err := dcrutil.NewAmount(utxo.Amount)
if err != nil {
return err
}
totalIn += uint64(amt)
details.Amount += amt
hash, err := chainhash.NewHashFromStr(utxo.TxID)
if err != nil {
Expand Down Expand Up @@ -154,7 +168,7 @@ func (w *Wallet) CreateSignedTransaction(ctx context.Context, outputs []*Output,
// while choosing inputs randomly.
inputSource = func(target dcrutil.Amount) (detail *txauthor.InputDetail, err error) {
for _, utxo := range unspents {
if details.Amount >= target {
if details.Amount >= target && !sendAll {
break
}
coinID := fmt.Sprintf("%s:%d", utxo.TxID, utxo.Vout)
Expand Down Expand Up @@ -188,29 +202,50 @@ func (w *Wallet) CreateSignedTransaction(ctx context.Context, outputs []*Output,
accountNum = 0
confs = 1
)
var msgTx *wire.MsgTx

atx, err := w.NewUnsignedTransaction(ctx, outs, dcrutil.Amount(feeRate), accountNum, confs,
wallet.OutputSelectionAlgorithmDefault, nil, inputSource)
if err != nil {
return nil, nil, 0, err
if sendAll {
txDetails, err := inputSource(dcrutil.Amount(totalIn))
if err != nil {
return nil, nil, 0, err
}
msgTx = wire.NewMsgTx()
msgTx.TxIn = txDetails.Inputs
msgTx.TxOut = outs
msgTx.TxOut[0].Value = int64(totalIn)
signedMsgTx, err := w.signRawTransaction(ctx, msgTx)
if err != nil {
return nil, nil, 0, err
}
fee = uint64(signedMsgTx.SerializeSize()) * feeRate / 1000
msgTx.TxOut[0].Value -= int64(fee)
if fee > totalIn || dexdcr.IsDust(msgTx.TxOut[0], feeRate) {
return nil, nil, 0, errors.New("output is dust, unable to send")
}
} else {
atx, err := w.NewUnsignedTransaction(ctx, outs, dcrutil.Amount(feeRate), accountNum, confs,
wallet.OutputSelectionAlgorithmDefault, nil, inputSource)
if err != nil {
return nil, nil, 0, err
}
msgTx = atx.Tx
fee = totalIn
for i := range msgTx.TxOut {
fee -= uint64(msgTx.TxOut[i].Value)
}
}

msgTx, err := w.signRawTransaction(ctx, atx.Tx)
signedMsgTx, err := w.signRawTransaction(ctx, msgTx)
if err != nil {
return nil, nil, 0, err
}

fee = uint64(atx.TotalInput)
for i := range atx.Tx.TxOut {
fee -= uint64(atx.Tx.TxOut[i].Value)
}

signedTx, err = msgTx.Bytes()
signedTx, err = signedMsgTx.Bytes()
if err != nil {
return nil, nil, 0, err
}

txHash := msgTx.TxHash()
txHash := signedMsgTx.TxHash()
return signedTx, &txHash, fee, nil
}

Expand Down
2 changes: 1 addition & 1 deletion cgo/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func createSignedTransaction(cName, cCreateSignedTxJSONReq *C.char) *C.char {
}
defer w.MainWallet().Lock()

txBytes, txhash, fee, err := w.CreateSignedTransaction(w.ctx, outputs, inputs, ignoreInputs, uint64(req.FeeRate))
txBytes, txhash, fee, err := w.CreateSignedTransaction(w.ctx, outputs, inputs, ignoreInputs, uint64(req.FeeRate), req.SendAll)
if err != nil {
return errCResponse("unable to sign send transaction: %v", err)
}
Expand Down
1 change: 1 addition & 0 deletions cgo/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ type CreateSignedTxReq struct {
Inputs []Input `json:"inputs"`
IgnoreInputs []Input `json:"ignoreinputs"`
FeeRate int `json:"feerate"`
SendAll bool `json:"sendall"`
Password string `json:"password"`
}

Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
github.com/decred/dcrd/chaincfg/v3 v3.2.1
github.com/decred/dcrd/connmgr/v3 v3.1.2
github.com/decred/dcrd/crypto/blake256 v1.0.1
github.com/decred/dcrd/dcrutil/v4 v4.0.2
github.com/decred/dcrd/hdkeychain/v3 v3.1.2
github.com/decred/dcrd/txscript/v4 v4.1.1
Expand All @@ -20,14 +21,14 @@ require (

require (
decred.org/cspp/v2 v2.2.0 // indirect
decred.org/dcrwallet/v3 v3.0.1 // indirect
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a // indirect
github.com/dchest/siphash v1.2.3 // indirect
github.com/decred/base58 v1.0.5 // indirect
github.com/decred/dcrd/blockchain/stake/v5 v5.0.1 // indirect
github.com/decred/dcrd/blockchain/standalone/v2 v2.2.1 // indirect
github.com/decred/dcrd/container/lru v1.0.0 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/crypto/rand v1.0.0 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/database/v3 v3.0.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ decred.org/cspp/v2 v2.2.0 h1:VSOUC1w0Wo+QOGS0r1XO6TLnO16X67KuvpDmRRYyr08=
decred.org/cspp/v2 v2.2.0/go.mod h1:9nO3bfvCheOPIFZw5f6sRQ42CjBFB5RKSaJ9Iq6G4MA=
decred.org/dcrdex v0.0.0-20240415203145-79c4689fd164 h1:ImD+Zui9lnZhVYacX0x9ki1M95hTYxwASl2PvVoAc2M=
decred.org/dcrdex v0.0.0-20240415203145-79c4689fd164/go.mod h1:rvIXDCS3B3gbu8b0tKDvNU664nC+/zVl3ivs6AeA2V8=
decred.org/dcrwallet/v3 v3.0.1 h1:+OLi+u/MvKc3Ubcnf19oyG/a5hJ/qp4OtezdiQZnLIs=
decred.org/dcrwallet/v3 v3.0.1/go.mod h1:a+R8BZIOKVpWVPat5VZoBWNh/cnIciwcRkPtrzfS/tw=
decred.org/dcrwallet/v4 v4.1.3 h1:XKxDbvPAHXfLunYNbCIEh2TYCwZ039hvUJCcTpfBAMg=
decred.org/dcrwallet/v4 v4.1.3/go.mod h1:hqAijllSbuhT4dZofpufi/08kGDXVUJUnPNtmqnJq4A=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
Expand Down

0 comments on commit 8b3c431

Please sign in to comment.