Skip to content

Commit

Permalink
update some logic in send and receive page
Browse files Browse the repository at this point in the history
  • Loading branch information
JustinBeBoy committed Jul 29, 2024
1 parent 7dddd8a commit b8d2698
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 49 deletions.
23 changes: 12 additions & 11 deletions libwallet/assets/btc/txauthor.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,17 +276,17 @@ func (asset *Asset) EstimateMaxSendAmount() (*sharedW.Amount, error) {
}

// Broadcast broadcasts the transaction to the network.
func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byte, error) {
func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) (string, error) {
if !asset.WalletOpened() {
return nil, utils.ErrBTCNotInitialized
return "", utils.ErrBTCNotInitialized
}

asset.TxAuthoredInfo.mu.Lock()
defer asset.TxAuthoredInfo.mu.Unlock()

unsignedTx, err := asset.unsignedTransaction()
if err != nil {
return nil, utils.TranslateError(err)
return "", utils.TranslateError(err)
}

// If the change output is the only one, no need to change position.
Expand All @@ -305,7 +305,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = asset.Internal().BTC.Unlock([]byte(privatePassphrase), lock)
if err != nil {
log.Errorf("unlocking the wallet failed: %v", err)
return nil, errors.New(utils.ErrInvalidPassphrase)
return "", errors.New(utils.ErrInvalidPassphrase)
}

// To discourage fee sniping, LockTime is explicitly set in the raw tx.
Expand All @@ -317,7 +317,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
_, previousTXout, _, _, err := asset.Internal().BTC.FetchInputInfo(&txIn.PreviousOutPoint)
if err != nil {
log.Errorf("fetch previous outpoint txout failed: %v", err)
return nil, err
return "", err
}

prevOutScript := unsignedTx.PrevScripts[index]
Expand All @@ -330,7 +330,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
)
if err != nil {
log.Errorf("generating input signatures failed: %v", err)
return nil, err
return "", err
}

msgTx.TxIn[index].Witness = witness
Expand All @@ -344,11 +344,11 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
prevOutAmount, prevOutFetcher)
if err != nil {
log.Errorf("creating validation engine failed: %v", err)
return nil, err
return "", err
}
if err := vm.Execute(); err != nil {
log.Errorf("executing the validation engine failed: %v", err)
return nil, err
return "", err
}
}

Expand All @@ -357,18 +357,19 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = msgTx.Serialize(&serializedTransaction)
if err != nil {
log.Errorf("encoding the tx to test its validity failed: %v", err)
return nil, err
return "", err
}

err = msgTx.Deserialize(bytes.NewReader(serializedTransaction.Bytes()))
if err != nil {
// Invalid tx
log.Errorf("decoding the tx to test its validity failed: %v", err)
return nil, err
return "", err
}

err = asset.Internal().BTC.PublishTransaction(msgTx, transactionLabel)
return nil, utils.TranslateError(err)
txHash := msgTx.TxHash()
return txHash.String(), utils.TranslateError(err)
}

func (asset *Asset) unsignedTransaction() (*txauthor.AuthoredTx, error) {
Expand Down
25 changes: 12 additions & 13 deletions libwallet/assets/dcr/txauthor.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,20 @@ func (asset *Asset) EstimateMaxSendAmount() (*sharedW.Amount, error) {
}, nil
}

func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byte, error) {
func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) (string, error) {
if !asset.WalletOpened() {
return nil, utils.ErrDCRNotInitialized
return "", utils.ErrDCRNotInitialized
}

n, err := asset.Internal().DCR.NetworkBackend()
if err != nil {
log.Error(err)
return nil, err
return "", err
}

unsignedTx, err := asset.unsignedTransaction()
if err != nil {
return nil, utils.TranslateError(err)
return "", utils.TranslateError(err)
}

if unsignedTx.ChangeIndex >= 0 {
Expand All @@ -233,15 +233,15 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = unsignedTx.Tx.Serialize(&txBuf)
if err != nil {
log.Error(err)
return nil, err
return "", err
}

var msgTx wire.MsgTx
err = msgTx.Deserialize(bytes.NewReader(txBuf.Bytes()))
if err != nil {
log.Error(err)
// Bytes do not represent a valid raw transaction
return nil, err
return "", err
}

lock := make(chan time.Time, 1)
Expand All @@ -253,15 +253,15 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = asset.Internal().DCR.Unlock(ctx, []byte(privatePassphrase), lock)
if err != nil {
log.Error(err)
return nil, errors.New(utils.ErrInvalidPassphrase)
return "", errors.New(utils.ErrInvalidPassphrase)
}

var additionalPkScripts map[wire.OutPoint][]byte

invalidSigs, err := asset.Internal().DCR.SignTransaction(ctx, &msgTx, txscript.SigHashAll, additionalPkScripts, nil, nil)
if err != nil {
log.Error(err)
return nil, err
return "", err
}

invalidInputIndexes := make([]uint32, len(invalidSigs))
Expand All @@ -274,22 +274,21 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = msgTx.Serialize(&serializedTransaction)
if err != nil {
log.Error(err)
return nil, err
return "", err
}

err = msgTx.Deserialize(bytes.NewReader(serializedTransaction.Bytes()))
if err != nil {
// Invalid tx
log.Error(err)
return nil, err
return "", err
}

txHash, err := asset.Internal().DCR.PublishTransaction(ctx, &msgTx, n)
if err != nil {
return nil, utils.TranslateError(err)
return "", utils.TranslateError(err)
}

return txHash[:], asset.updateTxLabel(txHash, transactionLabel)
return txHash.String(), asset.updateTxLabel(txHash, transactionLabel)
}

// updateTxLabel saves the tx label in the local instance.
Expand Down
23 changes: 12 additions & 11 deletions libwallet/assets/ltc/txauthor.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,17 @@ func (asset *Asset) EstimateMaxSendAmount() (*sharedW.Amount, error) {
}

// Broadcast broadcasts the transaction to the network.
func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byte, error) {
func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) (string, error) {
if !asset.WalletOpened() {
return nil, utils.ErrLTCNotInitialized
return "", utils.ErrLTCNotInitialized
}

asset.TxAuthoredInfo.mu.Lock()
defer asset.TxAuthoredInfo.mu.Unlock()

unsignedTx, err := asset.unsignedTransaction()
if err != nil {
return nil, utils.TranslateError(err)
return "", utils.TranslateError(err)
}

// If the change output is the only one, no need to change position.
Expand All @@ -281,7 +281,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = asset.Internal().LTC.Unlock([]byte(privatePassphrase), lock)
if err != nil {
log.Errorf("unlocking the wallet failed: %v", err)
return nil, errors.New(utils.ErrInvalidPassphrase)
return "", errors.New(utils.ErrInvalidPassphrase)
}

// To discourage fee sniping, LockTime is explicitly set in the raw tx.
Expand All @@ -293,7 +293,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
_, previousTXout, _, _, err := asset.Internal().LTC.FetchInputInfo(&txIn.PreviousOutPoint)
if err != nil {
log.Errorf("fetch previous outpoint txout failed: %v", err)
return nil, err
return "", err
}

prevOutScript := unsignedTx.PrevScripts[index]
Expand All @@ -306,7 +306,7 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
)
if err != nil {
log.Errorf("generating input signatures failed: %v", err)
return nil, err
return "", err
}

msgTx.TxIn[index].Witness = witness
Expand All @@ -320,11 +320,11 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
prevOutAmount, prevOutFetcher)
if err != nil {
log.Errorf("creating validation engine failed: %v", err)
return nil, err
return "", err
}
if err := vm.Execute(); err != nil {
log.Errorf("executing the validation engine failed: %v", err)
return nil, err
return "", err
}
}

Expand All @@ -333,18 +333,19 @@ func (asset *Asset) Broadcast(privatePassphrase, transactionLabel string) ([]byt
err = msgTx.Serialize(&serializedTransaction)
if err != nil {
log.Errorf("encoding the tx to test its validity failed: %v", err)
return nil, err
return "", err
}

err = msgTx.Deserialize(bytes.NewReader(serializedTransaction.Bytes()))
if err != nil {
// Invalid tx
log.Errorf("decoding the tx to test its validity failed: %v", err)
return nil, err
return "", err
}

err = asset.Internal().LTC.PublishTransaction(msgTx, transactionLabel)
return nil, utils.TranslateError(err)
txHash := msgTx.TxHash()
return txHash.String(), utils.TranslateError(err)
}

func (asset *Asset) unsignedTransaction() (*txauthor.AuthoredTx, error) {
Expand Down
2 changes: 1 addition & 1 deletion libwallet/assets/wallet/asset_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ type Asset interface {
NewUnsignedTx(accountNumber int32, utxos []*UnspentOutput) error
AddSendDestination(id int, address string, unitAmount int64, sendMax bool) error
ComputeTxSizeEstimation(dstAddress string, utxos []*UnspentOutput) (int, error)
Broadcast(passphrase, label string) ([]byte, error)
Broadcast(passphrase, label string) (string, error)
EstimateFeeAndSize() (*TxFeeAndSize, error)
IsUnsignedTxExist() bool
RemoveSendDestination(id int)
Expand Down
26 changes: 17 additions & 9 deletions ui/page/receive/receive_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ type Page struct {
selectedWallet sharedW.Asset
navigateToSyncBtn cryptomaterial.Button

closeButton cryptomaterial.Button
closeButton cryptomaterial.Button
qrCopyButton *widget.Clickable
addressCopyButton *widget.Clickable
}

func NewReceivePage(l *load.Load, wallet sharedW.Asset) *Page {
Expand All @@ -78,6 +80,8 @@ func NewReceivePage(l *load.Load, wallet sharedW.Asset) *Page {
newAddr: l.Theme.NewClickable(false),
card: l.Theme.Card(),
backdrop: new(widget.Clickable),
qrCopyButton: new(widget.Clickable),
addressCopyButton: new(widget.Clickable),
navigateToSyncBtn: l.Theme.Button(values.String(values.StrStartSync)),
selectedWallet: wallet,
}
Expand Down Expand Up @@ -315,7 +319,9 @@ func (pg *Page) contentLayout(gtx C) D {
if pg.qrImage == nil {
return D{}
}
return pg.Theme.ImageIcon(gtx, *pg.qrImage, 150)
return pg.qrCopyButton.Layout(gtx, func(gtx C) D {
return pg.Theme.ImageIcon(gtx, *pg.qrImage, 150)
})
}),
layout.Rigid(layout.Spacer{Height: values.MarginPadding24}.Layout),
layout.Rigid(pg.addressLayout),
Expand Down Expand Up @@ -426,12 +432,14 @@ func (pg *Page) addressLayout(gtx C) D {
}
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return border.Layout(gtx, func(gtx C) D {
return components.VerticalInset(values.MarginPadding12).Layout(gtx, func(gtx C) D {
lbl := pg.Theme.Label(values.TextSizeTransform(pg.IsMobileView(), values.TextSize16), "")
if pg.currentAddress != "" && pg.selectedWallet.IsSynced() {
lbl.Text = pg.currentAddress
}
return layout.Center.Layout(gtx, lbl.Layout)
return pg.addressCopyButton.Layout(gtx, func(gtx C) D {
return components.VerticalInset(values.MarginPadding12).Layout(gtx, func(gtx C) D {
lbl := pg.Theme.Label(values.TextSizeTransform(pg.IsMobileView(), values.TextSize16), "")
if pg.currentAddress != "" && pg.selectedWallet.IsSynced() {
lbl.Text = pg.currentAddress
}
return layout.Center.Layout(gtx, lbl.Layout)
})
})
})
}
Expand Down Expand Up @@ -495,7 +503,7 @@ generateAddress:

func (pg *Page) handleCopyEvent(gtx C) {
// Prevent copying again if the timer hasn't expired
if pg.copy.Clicked(gtx) && !pg.isCopying {
if (pg.copy.Clicked(gtx) || pg.qrCopyButton.Clicked(gtx) || pg.addressCopyButton.Clicked(gtx)) && !pg.isCopying {
gtx.Execute(clipboard.WriteCmd{Data: io.NopCloser(strings.NewReader(pg.currentAddress))})
pg.Toast.Notify(values.String(values.StrCopied))
}
Expand Down
11 changes: 10 additions & 1 deletion ui/page/send/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/crypto-power/cryptopower/ui/load"
"github.com/crypto-power/cryptopower/ui/modal"
"github.com/crypto-power/cryptopower/ui/page/components"
txpage "github.com/crypto-power/cryptopower/ui/page/transaction"
"github.com/crypto-power/cryptopower/ui/utils"
"github.com/crypto-power/cryptopower/ui/values"
)
Expand Down Expand Up @@ -607,7 +608,15 @@ func (pg *Page) HandleUserInteractions(gtx C) {

if pg.nextButton.Clicked(gtx) {
if pg.selectedWallet.IsUnsignedTxExist() {
pg.confirmTxModal = newSendConfirmModal(pg.Load, pg.authoredTxData, pg.selectedWallet)
pg.confirmTxModal = newSendConfirmModal(pg.Load, pg.authoredTxData, pg.selectedWallet, func(txHash string) {
if pg.modalLayout == nil {
transaction, err := pg.selectedWallet.GetTransactionRaw(txHash)
if err != nil {
log.Error("get transaction error: ", err)
}
pg.ParentNavigator().Display(txpage.NewTransactionDetailsPage(pg.Load, pg.selectedWallet, transaction))
}
})
pg.confirmTxModal.exchangeRateSet = pg.exchangeRate != -1 && pg.usdExchangeSet
// TODO handle if there are many description texts
// this workaround shows the description text when there is only one recipient and does not show when have more than one recipient
Expand Down
11 changes: 8 additions & 3 deletions ui/page/send/send_confirm_modal.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ type sendConfirmModal struct {
asset sharedW.Asset
exchangeRateSet bool
txLabel string
sentHandle func(string)
}

func newSendConfirmModal(l *load.Load, data *authoredTxData, asset sharedW.Asset) *sendConfirmModal {
func newSendConfirmModal(l *load.Load, data *authoredTxData, asset sharedW.Asset, sentHandle func(string)) *sendConfirmModal {
scm := &sendConfirmModal{
Load: l,
authoredTxData: data,
asset: asset,
sentHandle: sentHandle,
}
scm.Modal = l.Theme.ModalFloatTitle("send_confirm_modal", l.IsMobileView(), scm.firstLoad)

Expand Down Expand Up @@ -88,12 +90,15 @@ func (scm *sendConfirmModal) broadcastTransaction() {
scm.setLoading(true)
go func() {
defer scm.setLoading(false)
_, err := scm.asset.Broadcast(password, scm.txLabel)
txHash, err := scm.asset.Broadcast(password, scm.txLabel)
if err != nil {
scm.SetError(err.Error())
return
}
successModal := modal.NewSuccessModal(scm.Load, values.String(values.StrTxSent), modal.DefaultClickFunc())
successModal := modal.NewSuccessModal(scm.Load, values.String(values.StrTxSent), func(_ bool, _ *modal.InfoModal) bool {
scm.sentHandle(txHash)
return true
})
scm.ParentWindow().ShowModal(successModal)

scm.txSent()
Expand Down

0 comments on commit b8d2698

Please sign in to comment.