Skip to content

Commit

Permalink
client/asset/dcr: always show order options, make split default enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
chappjc committed Feb 24, 2023
1 parent 7981e7e commit 8794bd2
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 64 deletions.
68 changes: 32 additions & 36 deletions client/asset/dcr/dcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,9 @@ var (
"necessary. Otherwise, excess funds may be reserved to fund the order " +
"until the first swap contract is broadcast during match settlement, or " +
"the order is canceled. This an extra transaction for which network " +
"mining fees are paid. Used only for standing-type orders, e.g. " +
"limit orders without immediate time-in-force.",
"mining fees are paid.",
IsBoolean: true,
DefaultValue: false,
DefaultValue: true, // cheap fees, helpful for bond reserves, and adjustable at order-time
},
{
Key: "apifeefallback",
Expand Down Expand Up @@ -1396,9 +1395,12 @@ func (dcr *ExchangeWallet) maxOrder(lotSize, feeSuggestion, maxFeeRate uint64) (
// Start by attempting max lots with a basic fee.
basicFee := dexdcr.InitTxSize * maxFeeRate
lots := avail / (lotSize + basicFee)
cfg := dcr.config()
// NOTE: Split tx is an order-time option. The max order is generally
// attainable when split is used, regardless of whether they choose it on
// the order form. Allow the split for max order purposes.
trySplitTx := true
for lots > 0 {
est, _, _, err := dcr.estimateSwap(lots, lotSize, feeSuggestion, maxFeeRate, utxos, cfg.useSplitTx, 1.0)
est, _, _, err := dcr.estimateSwap(lots, lotSize, feeSuggestion, maxFeeRate, utxos, trySplitTx, 1.0)
// The only failure mode of estimateSwap -> dcr.fund is when there is
// not enough funds, so if an error is encountered, count down the lots
// and repeat until we have enough.
Expand Down Expand Up @@ -1513,7 +1515,7 @@ func (dcr *ExchangeWallet) PreSwap(req *asset.PreSwapForm) (*asset.PreSwap, erro
if err != nil {
return nil, err
}
if maxEst.Lots < req.Lots {
if maxEst.Lots < req.Lots { // changing options isn't going to fix this, only lots
return nil, fmt.Errorf("%d lots available for %d-lot order", maxEst.Lots, req.Lots)
}

Expand Down Expand Up @@ -1541,23 +1543,21 @@ func (dcr *ExchangeWallet) PreSwap(req *asset.PreSwapForm) (*asset.PreSwap, erro
est, _, _, err := dcr.estimateSwap(req.Lots, req.LotSize, req.FeeSuggestion,
req.MaxFeeRate, utxos, split, bump)
if err != nil {
return nil, fmt.Errorf("estimation failed: %v", err)
dcr.log.Warnf("estimateSwap failure: %v", err)
}

var opts []*asset.OrderOption

// Only offer the split option for standing orders.
if !req.Immediate {
if splitOpt := dcr.splitOption(req, utxos, bump); splitOpt != nil {
opts = append(opts, splitOpt)
}
}
// Always offer the split option, even for non-standing orders since
// immediately spendable change many be desirable regardless.
opts := []*asset.OrderOption{dcr.splitOption(req, utxos, bump)}

// Figure out what our maximum available fee bump is, within our 2x hard
// limit.
var maxBump float64
var maxBumpEst *asset.SwapEstimate
for maxBump = 2.0; maxBump > 1.01; maxBump -= 0.1 {
if est == nil {
break
}
tryEst, splitUsed, _, err := dcr.estimateSwap(req.Lots, req.LotSize,
req.FeeSuggestion, req.MaxFeeRate, utxos, split, maxBump)
// If the split used wasn't the configured value, this option is not
Expand Down Expand Up @@ -1610,7 +1610,7 @@ func (dcr *ExchangeWallet) PreSwap(req *asset.PreSwapForm) (*asset.PreSwap, erro
}

return &asset.PreSwap{
Estimate: est,
Estimate: est, // may be nil so we can present options, which in turn affect estimate feasibility
Options: opts,
}, nil
}
Expand Down Expand Up @@ -1657,40 +1657,39 @@ func (dcr *ExchangeWallet) SingleLotSwapFees(form *asset.PreSwapForm) (fees uint
// splitOption constructs an *asset.OrderOption with customized text based on the
// difference in fees between the configured and test split condition.
func (dcr *ExchangeWallet) splitOption(req *asset.PreSwapForm, utxos []*compositeUTXO, bump float64) *asset.OrderOption {
opt := &asset.OrderOption{
ConfigOption: asset.ConfigOption{
Key: splitKey,
DisplayName: "Pre-size Funds",
IsBoolean: true,
DefaultValue: dcr.config().useSplitTx, // not nil interface
ShowByDefault: true,
},
Boolean: &asset.BooleanConfig{},
}

noSplitEst, _, noSplitLocked, err := dcr.estimateSwap(req.Lots, req.LotSize,
req.FeeSuggestion, req.MaxFeeRate, utxos, false, bump)
if err != nil {
dcr.log.Errorf("estimateSwap (no split) error: %v", err)
return nil
opt.Boolean.Reason = fmt.Sprintf("estimate without a split failed with \"%v\"", err)
return opt // utility and overlock report unavailable, but show the option
}
splitEst, splitUsed, splitLocked, err := dcr.estimateSwap(req.Lots, req.LotSize,
req.FeeSuggestion, req.MaxFeeRate, utxos, true, bump)
if err != nil {
dcr.log.Errorf("estimateSwap (with split) error: %v", err)
return nil
}

opt := &asset.OrderOption{
ConfigOption: asset.ConfigOption{
Key: splitKey,
DisplayName: "Pre-size Funds",
IsBoolean: true,
DefaultValue: false, // not nil interface
ShowByDefault: true,
},
Boolean: &asset.BooleanConfig{},
opt.Boolean.Reason = fmt.Sprintf("estimate with a split failed with \"%v\"", err)
return opt // utility and overlock report unavailable, but show the option
}

if !splitUsed || splitLocked >= noSplitLocked { // locked check should be redundant
opt.Boolean.Reason = "avoids no DCR overlock for this order (ignored)"
opt.Description = "A split transaction for this order avoids no DCR overlock, but adds additional fees."
opt.DefaultValue = false
return opt // not enabled by default, but explain why
}

// Since it is usable, apply the user's default value, and set the
// reason and description.
opt.DefaultValue = dcr.config().useSplitTx

overlock := noSplitLocked - splitLocked
pctChange := (float64(splitEst.RealisticWorstCase)/float64(noSplitEst.RealisticWorstCase) - 1) * 100
if pctChange > 1 {
Expand Down Expand Up @@ -1842,9 +1841,6 @@ func (dcr *ExchangeWallet) FundOrder(ord *asset.Order) (asset.Coins, []dex.Bytes
if customCfg.Split != nil {
useSplit = *customCfg.Split
}
if ord.Immediate {
useSplit = false
}

changeForReserves := useSplit && cfg.unmixedAccount == ""
reserves := dcr.reserves()
Expand Down
2 changes: 1 addition & 1 deletion client/webserver/site/src/html/bodybuilder.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
{{end}}

{{define "bottom"}}
<script src="/js/entry.js?v=Om9tNpJl"></script>
<script src="/js/entry.js?v=eGfPLtv5"></script>
</body>
</html>
{{end}}
56 changes: 29 additions & 27 deletions client/webserver/site/src/html/markets.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -562,36 +562,38 @@
<div class="fs15 pt-3 text-center d-hide errcolor text-break" id="vErr"></div>{{- /* End Auth Section */ -}}

<div id="vPreorder">
<hr class="dashed mb-2 mt-3">
<div id="vPreorderEstimates">
<hr class="dashed mb-2 mt-3">

<div class="d-flex justify-content-between align-items-center">
<span class="grey fs18">
[[[Fee Projection]]]
<span class="ico-info fs12" data-tooltip="[[[fee_projection_tooltip]]]"></span>
</span>
<span class="grey fs14 underline pointer hoverbg" id="vFeeDetails">[[[details]]]</span>
</div>

<div class="py-1 d-flex align-items-center justify-content-center fs18" id="vFeeSummaryPct">
<span id="vFeeSummaryLow"></span>
<span class="fs15">%</span>
<span class="fs15 px-2">[[[to]]]</span>
<span id="vFeeSummaryHigh"></span>
<span class="fs15">%</span>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="grey fs18">
[[[Fee Projection]]]
<span class="ico-info fs12" data-tooltip="[[[fee_projection_tooltip]]]"></span>
</span>
<span class="grey fs14 underline pointer hoverbg" id="vFeeDetails">[[[details]]]</span>
</div>

<div class="py-1 flex-column align-items-center justify-content-center fs18" id="vFeeSummary">
<div class="d-flex flex-row align-items-center justify-content-center">
<img class="micro-icon mx-1" data-icon="from">
<span id="summarySwapFeesLow"></span>
<span class="px-1">&ndash;</span>
<span id="summarySwapFeesHigh"></span>
<div class="py-1 d-flex align-items-center justify-content-center fs18" id="vFeeSummaryPct">
<span id="vFeeSummaryLow"></span>
<span class="fs15">%</span>
<span class="fs15 px-2">[[[to]]]</span>
<span id="vFeeSummaryHigh"></span>
<span class="fs15">%</span>
</div>
<div class="d-flex flex-row align-items-center justify-content-center">
<img class="micro-icon mx-1" data-icon="to">
<span id="summaryRedeemFeesLow"></span>
<span class="px-1">&ndash;</span>
<span id="summaryRedeemFeesHigh"></span>

<div class="py-1 flex-column align-items-center justify-content-center fs18" id="vFeeSummary">
<div class="d-flex flex-row align-items-center justify-content-center">
<img class="micro-icon mx-1" data-icon="from">
<span id="summarySwapFeesLow"></span>
<span class="px-1">&ndash;</span>
<span id="summarySwapFeesHigh"></span>
</div>
<div class="d-flex flex-row align-items-center justify-content-center">
<img class="micro-icon mx-1" data-icon="to">
<span id="summaryRedeemFeesLow"></span>
<span class="px-1">&ndash;</span>
<span id="summaryRedeemFeesHigh"></span>
</div>
</div>
</div>

Expand Down
6 changes: 6 additions & 0 deletions client/webserver/site/src/js/markets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1803,6 +1803,11 @@ export default class MarketsPage extends BasePage {
/* setFeeEstimates sets all of the pre-order estimate fields */
setFeeEstimates (swap: PreSwap, redeem: PreRedeem, order: TradeForm) {
const { page, market } = this
if (!swap.estimate || !redeem.estimate) {
Doc.hide(page.vPreorderEstimates)
return // preOrder may return just options, no fee estimates
}
Doc.show(page.vPreorderEstimates)
const { baseUnitInfo, quoteUnitInfo, rateConversionFactor } = market
const fmtPct = (value: number) => {
if (value < 0.05) return '< 0.1'
Expand Down Expand Up @@ -2124,6 +2129,7 @@ export default class MarketsPage extends BasePage {
/* handleBalanceNote handles notifications updating a wallet's balance. */
handleBalanceNote (note: BalanceNote) {
this.setBalanceVisibility()
this.preorderCache = {} // invalidate previous preorder results
// if connection to dex server fails, it is not possible to retrieve
// markets.
const mkt = this.market
Expand Down

0 comments on commit 8794bd2

Please sign in to comment.