Skip to content

Commit

Permalink
add UI to update bond options
Browse files Browse the repository at this point in the history
  • Loading branch information
ukane-philemon authored and chappjc committed Feb 26, 2023
1 parent 9e59e53 commit 622fe7d
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 9 deletions.
9 changes: 5 additions & 4 deletions client/core/bond.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
return errors.New("login or register first")
}

// Revert to initial vals on any error.
// Revert to initial values if we encounter any error below.
bondAssetID0 = dc.acct.bondAsset
targetTier0, maxBondedAmt0 = dc.acct.targetTier, dc.acct.maxBondedAmt
totalReserved0 := dc.acct.totalReserved
Expand Down Expand Up @@ -1202,15 +1202,16 @@ func (c *Core) makeAndPostBond(dc *dexConnection, acctExists bool, wallet *xcWal
bondCoinStr, unbip(bond.AssetID), dc.acct.host, err)
}
} else {
bondAsset, targetTier, maxBondedAmt := dc.bondOpts()
ai := &db.AccountInfo{
Host: dc.acct.host,
Cert: dc.acct.cert,
DEXPubKey: dc.acct.dexPubKey,
EncKeyV2: dc.acct.encKey,
Bonds: []*db.Bond{dbBond},
TargetTier: dc.acct.targetTier,
MaxBondedAmt: dc.acct.maxBondedAmt,
BondAsset: dc.acct.bondAsset,
TargetTier: targetTier,
MaxBondedAmt: maxBondedAmt,
BondAsset: bondAsset,
}
err = c.dbCreateOrUpdateAccount(dc, ai)
if err != nil {
Expand Down
9 changes: 8 additions & 1 deletion client/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ func (dc *dexConnection) exchangeInfo() *Exchange {
dc.acct.authMtx.RLock()
// TODO: List bonds in core.Exchange. For now, just tier.
tier := dc.acct.tier
bondAssetID := dc.acct.bondAsset
targetTier, maxBondedAmt := dc.acct.targetTier, dc.acct.maxBondedAmt
dc.acct.authMtx.RUnlock()

return &Exchange{
Expand All @@ -507,7 +509,12 @@ func (dc *dexConnection) exchangeInfo() *Exchange {
CandleDurs: cfg.BinSizes,
ViewOnly: dc.acct.isViewOnly(),
Tier: tier,
PendingBonds: dc.pendingBonds(),
BondOptions: &BondOptions{
BondAsset: bondAssetID,
TargetTier: targetTier,
MaxBondedAmt: maxBondedAmt,
},
PendingBonds: dc.pendingBonds(),
// TODO: Bonds

// Legacy reg fee (V0PURGE)
Expand Down
8 changes: 8 additions & 0 deletions client/core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,13 @@ type PendingBondState struct {
// PendingFeeState is deprecated (V0PURGE), but the same as PendingBondState.
type PendingFeeState PendingBondState

// BondOptions are auto-bond maintenance settings for a particular DEX.
type BondOptions struct {
BondAsset uint32 `json:"bondAsset"`
TargetTier uint64 `json:"targetTier"`
MaxBondedAmt uint64 `json:"maxBondedAmt"`
}

// Exchange represents a single DEX with any number of markets.
type Exchange struct {
Host string `json:"host"`
Expand All @@ -621,6 +628,7 @@ type Exchange struct {
CandleDurs []string `json:"candleDurs"`
ViewOnly bool `json:"viewOnly"`
Tier int64 `json:"tier"`
BondOptions *BondOptions `json:"bondOptions"`
PendingBonds map[string]*PendingBondState `json:"pendingBonds"`
// TODO: Bonds slice(s) - and a LockedInBonds(assetID) method

Expand Down
16 changes: 16 additions & 0 deletions client/webserver/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ func (s *WebServer) apiPostBond(w http.ResponseWriter, r *http.Request) {
writeJSON(w, simpleAck(), s.indent)
}

// apiUpdateBondOptions is the handler for the '/updatebondoptions' API request.
func (s *WebServer) apiUpdateBondOptions(w http.ResponseWriter, r *http.Request) {
form := new(core.BondOptionsForm)
if !readPost(w, r, form) {
return
}

err := s.core.UpdateBondOptions(form)
if err != nil {
s.writeAPIError(w, fmt.Errorf("update bond options error: %w", err))
return
}

writeJSON(w, simpleAck(), s.indent)
}

// apiNewWallet is the handler for the '/newwallet' API request.
func (s *WebServer) apiNewWallet(w http.ResponseWriter, r *http.Request) {
form := new(newWalletForm)
Expand Down
3 changes: 3 additions & 0 deletions client/webserver/live_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,9 @@ func (c *TCore) Register(r *core.RegisterForm) (*core.RegisterResult, error) {
func (c *TCore) PostBond(r *core.PostBondForm) (*core.PostBondResult, error) {
return nil, nil
}
func (c *TCore) UpdateBondOptions(form *core.BondOptionsForm) error {
return nil
}
func (c *TCore) EstimateRegistrationTxFee(host string, certI interface{}, assetID uint32) (uint64, error) {
xc := tExchanges[host]
if xc == nil {
Expand Down
4 changes: 4 additions & 0 deletions client/webserver/locales/en-us.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ var EnUS = map[string]string{
"app_pw_reg": "Enter your app password to confirm DEX registration.",
"reg_confirm_submit": `When you submit this form, funds will be spent from your wallet to pay the registration fee.`,
"bond_strength": "Bond Strength",
"update_bond_options": "Update Bond Options",
"bond_options_update_success": "Bond Options have been updated successfully",
"target_tier": "Target Tier",
"target_tier_tooltip": "This is the target account tier you wish to maintain. Set to zero if you wish to disable tier maintenance.",
"provided_markets": "This DEX provides the following markets:",
"accepted_fee_assets": "This DEX accepts the following fees:",
"base_header": "Base",
Expand Down
3 changes: 2 additions & 1 deletion client/webserver/site/src/css/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ button.form-button {
#dexAddrForm,
#verifyForm,
#appPWForm,
#deleteArchivedRecordsForm {
#deleteArchivedRecordsForm,
#updateBondOptionsForm {
width: 325px;
}

Expand Down
29 changes: 28 additions & 1 deletion client/webserver/site/src/html/dexsettings.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
</div>
<div class="fs15 pt-3 text-center d-hide errcolor text-break" id="errMsg"></div>
<div class="settings">
<div {{if .Exchange.ViewOnly}} class="d-hide"{{end}}>
<div{{if .Exchange.ViewOnly}} class="d-hide"{{end}}>
<button id="exportDexBtn" class="bg2 selected">[[[Export Account]]]</button>
</div>
<div>
<button id="disableAcctBtn" class="bg2 selected">[[[Disable Account]]]</button>
</div>
<div{{if .Exchange.ViewOnly}} class="d-hide"{{end}}>
<button id="updateBondOptionsBtn" class="bg2 selected">[[[update_bond_options]]]</button>
</div>
<div>
<input type="file" class="form-control select d-none" id="certFileInput">
<button id="updateCertBtn" class="bg2 selected">[[[Update TLS Certificate]]]</button>
Expand All @@ -42,6 +45,30 @@
<form class="d-hide" id="dexAddrForm" autocomplete="off">
{{template "dexAddrForm" .}}
</form>

{{- /* UPDATE BOND OPTIONS */ -}}
<form class="d-hide" id="updateBondOptionsForm" autocomplete="off">
<div class="py-1 text-center fs28 sans-light">[[[update_bond_options]]]</div>
<div class="selectBondAsset mt-3">
<label for="bondAssetSelect" class="form-label">[[[Asset]]]</label>
<select id="bondAssetSelect" class="w-100"></select>
</div>

<div class="mt-3">
<label for="bondTargetTier" class="form-label">
[[[target_tier]]]
<span class="ico-info fs12" data-tooltip="[[[target_tier_tooltip]]]"></span>
</label>
<input type="number" min="0" class="form-control select bg1" id="bondTargetTier" autocomplete="off">
</div>

<div class="d-flex justify-content-end mt-3">
<button id="updateBondOptionsConfirm" class="submit bg2 fs18 selected">[[[Submit]]]</button>
</div>
<div id="bondOptionsErr" class="fs15 pt-3 text-center d-hide errcolor text-break"></div>
<div id="bondOptionsMsg" class="fs15 pt-3 text-center d-hide text-break">[[[bond_options_update_success]]]</div>
</form>

</div>

</div>
Expand Down
55 changes: 55 additions & 0 deletions client/webserver/site/src/js/dexsettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default class DexSettingsPage extends BasePage {

Doc.bind(page.exportDexBtn, 'click', () => this.prepareAccountExport(page.authorizeAccountExportForm))
Doc.bind(page.disableAcctBtn, 'click', () => this.prepareAccountDisable(page.disableAccountForm))
Doc.bind(page.updateBondOptionsBtn, 'click', () => this.prepareUpdateBondOptions())
Doc.bind(page.updateCertBtn, 'click', () => page.certFileInput.click())
Doc.bind(page.updateHostBtn, 'click', () => this.prepareUpdateHost())
Doc.bind(page.certFileInput, 'change', () => this.onCertFileChange())
Expand All @@ -40,6 +41,7 @@ export default class DexSettingsPage extends BasePage {
window.location.assign(`/dexsettings/${xc.host}`)
}, undefined, this.host)

forms.bind(page.updateBondOptionsForm, page.updateBondOptionsConfirm, () => this.updateBondOptions())
forms.bind(page.authorizeAccountExportForm, page.authorizeExportAccountConfirm, () => this.exportAccount())
forms.bind(page.disableAccountForm, page.disableAccountConfirm, () => this.disableAccount())

Expand Down Expand Up @@ -153,6 +155,24 @@ export default class DexSettingsPage extends BasePage {
this.showForm(disableAccountForm)
}

// prepareUpdateBondOptions resets and prepares the Update Bond Options form.
async prepareUpdateBondOptions () {
const page = this.page
const xc = app().user.exchanges[this.host]
page.bondTargetTier.setAttribute('placeholder', xc.bondOptions.targetTier.toString())
Doc.empty(page.bondAssetSelect)
for (const [assetSymbol, bondAsset] of Object.entries(xc.bondAssets)) {
const option = document.createElement('option') as HTMLOptionElement
option.value = bondAsset.id.toString()
option.textContent = assetSymbol.toUpperCase()
if (bondAsset.id === xc.bondOptions.bondAsset) option.selected = true
page.bondAssetSelect.appendChild(option)
}
page.bondOptionsErr.textContent = ''
Doc.hide(page.bondOptionsErr)
this.showForm(page.updateBondOptionsForm)
}

async prepareUpdateHost () {
const page = this.page
this.dexAddrForm.refresh()
Expand Down Expand Up @@ -207,4 +227,39 @@ export default class DexSettingsPage extends BasePage {
}
}
}

/*
* updateBondOptions is called when the form to update bond options is
* submitted.
*/
async updateBondOptions () {
const page = this.page
const targetTier = parseInt(page.bondTargetTier.value ?? '')
const bondAsset = parseInt(page.bondAssetSelect.value ?? '')

const bondOptions = {
host: this.host,
targetTier: targetTier,
bondAsset: bondAsset
}

const loaded = app().loading(this.body)
const res = await postJSON('/api/updatebondoptions', bondOptions)
loaded()
if (!app().checkResponse(res)) {
page.bondOptionsErr.textContent = res.msg
Doc.show(page.bondOptionsErr)
} else {
Doc.hide(page.bondOptionsErr)
Doc.show(page.bondOptionsMsg)
setTimeout(() => {
Doc.hide(page.bondOptionsMsg)
Doc.hide(page.forms)
}, 5000)
// update the in-memory values.
const xc = app().user.exchanges[this.host]
xc.bondOptions.bondAsset = bondAsset
xc.bondOptions.targetTier = targetTier
}
}
}
4 changes: 2 additions & 2 deletions client/webserver/site/src/js/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ interface WalletConfig {

/*
* NewWalletForm should be used with the "newWalletForm" template. The enclosing
* <form> element should be the second argument of the constructor.
* <form> element should be the first argument of the constructor.
*/
export class NewWalletForm {
page: Record<string, PageElement>
Expand Down Expand Up @@ -726,7 +726,7 @@ export class ConfirmRegistrationForm {
this.pwCache = pwCache

Doc.bind(this.page.goBack, 'click', () => goBack())
Doc.bind(this.page.bondStrengthField, 'change', () => {
Doc.bind(this.page.bondStrengthField, 'input', () => {
const asset = app().assets[this.feeAssetID]
if (!asset) return
const ui = asset.unitInfo
Expand Down
7 changes: 7 additions & 0 deletions client/webserver/site/src/js/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export enum ConnectionStatus {
InvalidCert = 2,
}

export interface BondOptions {
bondAsset: number
targetTier: number
maxBondedAmt: number
}

export interface Exchange {
host: string
acctID: string
Expand All @@ -23,6 +29,7 @@ export interface Exchange {
viewOnly: boolean
bondAssets: Record<string, BondAsset>
tier: number
bondOptions: BondOptions
pendingBonds: Record<string, PendingBondState>
candleDurs: string[]
}
Expand Down
2 changes: 2 additions & 0 deletions client/webserver/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type clientCore interface {
Exchange(host string) (*core.Exchange, error)
Register(*core.RegisterForm) (*core.RegisterResult, error)
PostBond(form *core.PostBondForm) (*core.PostBondResult, error)
UpdateBondOptions(form *core.BondOptionsForm) error
Login(pw []byte) error
InitializeClient(pw, seed []byte) error
AssetBalance(assetID uint32) (*core.WalletBalance, error)
Expand Down Expand Up @@ -380,6 +381,7 @@ func New(cfg *Config) (*WebServer, error) {
apiAuth.Post("/defaultwalletcfg", s.apiDefaultWalletCfg)
apiAuth.Post("/register", s.apiRegister)
apiAuth.Post("/postbond", s.apiPostBond)
apiAuth.Post("/updatebondoptions", s.apiUpdateBondOptions)
apiAuth.Post("/newwallet", s.apiNewWallet)
apiAuth.Post("/openwallet", s.apiOpenWallet)
apiAuth.Post("/depositaddress", s.apiNewDepositAddress)
Expand Down
3 changes: 3 additions & 0 deletions client/webserver/webserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ func (c *TCore) Register(r *core.RegisterForm) (*core.RegisterResult, error) { r
func (c *TCore) PostBond(r *core.PostBondForm) (*core.PostBondResult, error) {
return nil, c.postBondErr
}
func (c *TCore) UpdateBondOptions(form *core.BondOptionsForm) error {
return c.postBondErr
}
func (c *TCore) EstimateRegistrationTxFee(host string, certI interface{}, assetID uint32) (uint64, error) {
return 0, nil
}
Expand Down

0 comments on commit 622fe7d

Please sign in to comment.