Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client/core: hide order form and display registration status message #353

Merged
merged 8 commits into from
Jun 1, 2020

Conversation

fernandoabolafio
Copy link
Member

@fernandoabolafio fernandoabolafio commented May 10, 2020

This PR modifies the code so the order form is hidden while the registration payment has not been confirmed. Instead, a message is shown to communicate the status of the confirmation. See the previews for more info.

The full list of changes:

Core changes:

  • Adds the dex URL to all feepayment notifications. This is particularly useful in this case to determine to either show or not the confirmation message in the current market.
  • The registration update notification uses now the regupdated subject.
  • Successful registration note uses now the regcompleted subject. So it server to multiple purposes in the frontend side. See 'Site changes' for more info.
  • Refresh the user after completed registration.

Site changes:

  • Added an override handler in the app.js which enables the overriding of notifications subject. This is useful to have a notification serving multiple purposes, such as the 'regcompleted' in this case where it is both displayed in the notifications dropdown and it is used to display the order form once the registration payment has been successful.
  • The market app page now handles feepayment notifications and update the exchanges confirmations as well the feePending value.
  • Hide 'order form' and display the 'registration status' while the fee payment has not been confirmed. Once it is confirmed, a success message is shown for 5 seconds and the order form is set as visible again.

UI Preview:

Screenshot 2020-05-08 at 12 34 18
Screenshot 2020-05-08 at 12 33 36
Screenshot 2020-05-08 at 12 33 09

closes #337

Copy link
Member

@buck54321 buck54321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests well.

client/core/core.go Outdated Show resolved Hide resolved
client/webserver/site/src/css/market.scss Outdated Show resolved Hide resolved
client/webserver/site/src/html/markets.tmpl Outdated Show resolved Hide resolved
client/webserver/site/src/html/markets.tmpl Outdated Show resolved Hide resolved
client/webserver/site/src/js/app.js Outdated Show resolved Hide resolved
client/core/core.go Outdated Show resolved Hide resolved
client/webserver/site/src/js/markets.js Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
@chappjc
Copy link
Member

chappjc commented May 14, 2020

@fernandoabolafio Minor conflict to resolve please.

@fernandoabolafio
Copy link
Member Author

@chappjc thanks for the heads up I am still working on some changes. I will fix all conflicts once I am done.

@fernandoabolafio
Copy link
Member Author

@buck54321 I addressed all of your comments. The code looks much simpler now. Major changes are:

  • Instead of tracking the registration status with a new object, I am just using the user.exchanges. The tracking happens only in the App level and the loaded page is notified using a new method called registrationStatusUpdated.
  • I added confsRequired to the exchange object so now it doesn't need to be provided with notifications and the app is aware of this information from the start.

Copy link
Member

@buck54321 buck54321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot cleaner this way, but I think we can make it even better. See what you think of these recommendations.

client/webserver/site/src/js/basepage.js Outdated Show resolved Hide resolved
client/webserver/site/src/js/app.js Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
client/webserver/site/src/js/markets.js Show resolved Hide resolved
client/webserver/site/src/js/doc.js Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
Copy link
Member Author

@fernandoabolafio fernandoabolafio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@buck54321 thanks for your review! I addressed your changes and left two comments/questions for you.

client/core/core.go Show resolved Hide resolved
Copy link
Member

@buck54321 buck54321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. Just some touchups.

client/rpcserver/handlers.go Outdated Show resolved Hide resolved
client/rpcserver/handlers_test.go Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
client/webserver/site/src/js/markets.js Outdated Show resolved Hide resolved
const dexUrl = note.dexurl
if (dexUrl !== this.market.dex.url) return
// update local dex
this.market.dex = app.exchanges[dexUrl]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking around now, I'm noticing that this.market.dex is only ever used for the dex.url. Maybe we should just set the field as this.market.dexAddr, which won't change, so we don't have to update the dex object after fetchUser is called.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm. I don't think I follow you on this one. We also use this.market.dex to get the confs and confsRequired and that's the major reason we update the dex value.
See here.

client/webserver/site/src/html/markets.tmpl Outdated Show resolved Hide resolved
client/rpcserver/handlers.go Outdated Show resolved Hide resolved
client/core/notification.go Outdated Show resolved Hide resolved
client/core/notification.go Outdated Show resolved Hide resolved
@fernandoabolafio
Copy link
Member Author

@buck54321 thanks again for the comments! All the comments were addressed with the exception of this one: #353 (comment) where I left a question for you.

@chappjc
Copy link
Member

chappjc commented May 21, 2020

url -> host rename created a couple very minor conflicts.

Also master broke some js stuff. Fixed in
(note "excecuted" typo is fixed in #399) though so that should probably go in first.
merged

*/
handleFeePayment (note) {
const dexAddr = note.dex
if (dexAddr !== this.market.dex.url) return
Copy link
Member

@chappjc chappjc May 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that dex.url is now dex.host, with some related fixes in the now-merged PR #399 .

@chappjc
Copy link
Member

chappjc commented May 22, 2020

PR #399 fixing some url/host variable name issues now merged. Should be able to resolve and update to use dex.host instead of dex.url in your new code. Thanks and sorry for the repeated conflicts! Lots of concurrent work on the same files right now.

@fernandoabolafio fernandoabolafio force-pushed the 337_hide-order-forms branch 2 times, most recently from cb5888a to 01525f4 Compare May 23, 2020 19:57
return &FeePaymentNote{
Notification: db.NewNotification("fee payment", subject, details, severity),
Notification: db.NewNotification("feepayment", subject, details, severity),
Dex: addrHost(dexAddr),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chappjc thanks for the heads up. I updated the code to use the dex host instead. The feepayment is also sending the host by making sure to transform dexAddr using the addrHost helper.

@fernandoabolafio fernandoabolafio requested a review from chappjc May 23, 2020 20:04
Copy link
Member

@buck54321 buck54321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, but there may be an issue having to do with the recent work in #322. When I first create my account, the screen is all good. If I then click on a market with an unsupported asset, It's also still okay, though the styling could use some work

Then, if I click on the dcr-btc market again, both the the confirmations message and the order form are shown

}

/*
* handleFeePaymentNote is the handler for the 'feepayment'-type notificaetion, which
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notificaetion

@fernandoabolafio
Copy link
Member Author

@buck54321 I addressed the changes you requested:

  • Added a method called resolveOrderFormVisibility which is used every time another methods wants to update the orderForm visibility. The conditions which changes the form visibility are defined inside resolveOrderFormVisibility.
  • Simplified a bit the code at the end of setMarket and merged the 'loaderMsg' functions (hide/show) into a single one.
  • Add to 'query methods' hasFeePending and assetsAreSupported which are used to ease the readability and encapsulate logic we are reusing.
  • Style tweak:
    Screenshot 2020-05-26 at 18 52 39
    Screenshot 2020-05-26 at 18 53 39

Copy link
Member

@chappjc chappjc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there is a data race on dexConnection.regConfirms. Also, I don't care much for it being a pointer in dexConnection, although I see why it's needed that way in the Exchange type, so that's OK I suppose.

FeePending: dc.acct.feePending(),
Connected: dc.connected,
ConfsRequired: uint32(dc.cfg.RegFeeConfirms),
RegConfirms: dc.regConfirms,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refreshUser=>Exchanges reading dc.regConfirms can happen in many places, but regConfirms is not guarded (connMtx is for Core.conns, not for these fields of dexConnection).

return
}

dc.regConfirms = &regConfs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible concurrent write if refreshUser or Exchanges is called elsewhere.

} else {
details := fmt.Sprintf("You may now trade at %s", dc.acct.url)
c.notify(newFeePaymentNote("Account registered", details, db.Success))
dc.regConfirms = nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible concurrent write.

FeePending bool `json:"feePending"`
Connected bool `json:"connected"`
ConfsRequired uint32 `json:"confsrequired"`
RegConfirms *uint32 `json:"confs,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only needs to be a pointer in Exchange for purposes of omitempty, but it's a bit awkward as a pointer in dexConnection. The alternative would be to have -1 or 0 be special values in dexConnection.regConfirms that indicate to write nil to Exchange.RegConfirms in (*Core).Exchanges.

Track registration status in the application level

rename 'url' -> 'dexAddr'

Make sure to pass the exchange host in the fee payment note
… a few more tweaks to prevent conflicts while controlling the order form visibility state
Copy link
Member Author

@fernandoabolafio fernandoabolafio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chappjc thanks for the review. I addressed your comments. Explanation of the changes below:

Comment on lines +75 to +76
regConfMtx sync.RWMutex
regConfirms uint32
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a sync.RWMutex to be used when writing/reading regConfirms

Comment on lines 124 to 133
// getRegConfirms returns the number of confirmations received for the
// dex registration or nil if the registration is completed
func (dc *dexConnection) getRegConfirms() *uint32 {
dc.regConfMtx.RLock()
defer dc.regConfMtx.RUnlock()
if dc.regConfirms == regConfirmationsPaid {
return nil
}
return &dc.regConfirms
}
Copy link
Member Author

@fernandoabolafio fernandoabolafio Jun 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getRegConfirms returns an uint32 pointer that can be used in the core.Exchanges. It will return the number of confirmations or nil if the registration has been completed.
Notice that different from your suggestion I used a high number called regConfirmationsPaid to indicate that the confirmation is completed.
I could not use 0 because it just means that the registration is ongoing and no confirmation has been received so far. Using -1 requires converting the dexConnection.regConfirms to int32 which hurts the semantic of the code and would also for me to convert the Exchange field to int at some point.


// setRegConfirms sets the number of confirmations received
// for the dex registration
func (dc *dexConnection) setRegConfirms(confs uint32) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simple method to update regConfirms which deals with the synchronization internally.

@@ -36,6 +36,9 @@ const (
keyParamsKey = "keyParams"
conversionFactor = 1e8
regFeeAssetSymbol = "dcr" // Hard-coded to Decred for registration fees, for now.
// high number to be assigned to 'regConfirms' in 'dexConnection'
// when the registration is completed
regConfirmationsPaid uint32 = 9999
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'PNOOMA' number used to represent that the confirmation is completed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, although note this is actually realistic for many ccs. e.g. ETH: https://blog.coinbase.com/announcing-new-confirmation-requirements-4a5504ba8d81

@fernandoabolafio fernandoabolafio requested a review from chappjc June 1, 2020 10:10
@@ -497,7 +520,7 @@ func (c *Core) Exchanges() map[string]*Exchange {
FeePending: dc.acct.feePending(),
Connected: dc.connected,
ConfsRequired: uint32(dc.cfg.RegFeeConfirms),
RegConfirms: dc.regConfirms,
RegConfirms: dc.getRegConfirms(),
Copy link
Member

@chappjc chappjc Jun 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When code dereferences this Exchange.RegConfirms pointer, it's accessing dexConnection.regConfirms becausegetRegConfirms does return &dc.regConfirms. So this is basically sidestepping the locking as when another goroutine calls dc.setRegConfirms it is not locked anymore.

You need to either have getRegConfirms return a plain uint32 or make a copy inside the function and return a pointer to the copy (confs := dc.regConfirms; return &confs).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! I changed it to return the copy instead.

@chappjc chappjc merged commit 7654f9d into decred:master Jun 1, 2020
@fernandoabolafio fernandoabolafio deleted the 337_hide-order-forms branch June 1, 2020 19:59
buck54321 added a commit to buck54321/dcrdex that referenced this pull request Jun 9, 2020
The field was changed to a reference in a later commit of decred#353,
but that meant that it was recognized as waiting for confirmations
on startup, since it would be zero. Pointer works better in this
case.
chappjc pushed a commit that referenced this pull request Jun 11, 2020
The field was changed to a reference in a later commit of #353,
but that meant that it was recognized as waiting for confirmations
on startup, since it would be zero. Pointer works better in this
case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

app: hide order forms when registration is incomplete
3 participants