+
+
diff --git a/client/core/bond.go b/client/core/bond.go
index 1640ca61e9..eab1e09539 100644
--- a/client/core/bond.go
+++ b/client/core/bond.go
@@ -458,6 +458,10 @@ func (c *Core) bondStateOfDEX(dc *dexConnection, bondCfg *dexBondCfg) *dexAcctBo
return state
}
+func (c *Core) exchangeAuth(dc *dexConnection) *ExchangeAuth {
+ return &c.bondStateOfDEX(dc, c.dexBondConfig(dc, time.Now().Unix())).ExchangeAuth
+}
+
type bondID struct {
assetID uint32
coinID []byte
@@ -908,7 +912,7 @@ func (c *Core) monitorBondConfs(dc *dexConnection, bond *asset.Bond, reqConfs ui
if confs < reqConfs {
details := fmt.Sprintf("Bond confirmations %v/%v", confs, reqConfs)
c.notify(newBondPostNoteWithConfirmations(TopicRegUpdate, string(TopicRegUpdate),
- details, db.Data, assetID, coinIDStr, int32(confs), host))
+ details, db.Data, assetID, coinIDStr, int32(confs), host, c.exchangeAuth(dc)))
}
return confs >= reqConfs, nil
@@ -982,12 +986,12 @@ func (c *Core) nextBondKey(assetID uint32) (*secp256k1.PrivateKey, uint32, error
// the target trading tier, the preferred asset to use for bonds, and the
// maximum amount allowable to be locked in bonds.
func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
- dc, _, err := c.dex(form.Addr)
+ dc, _, err := c.dex(form.Host)
if err != nil {
return err
}
// TODO: exclude unregistered and/or watch-only
- dbAcct, err := c.db.Account(form.Addr)
+ dbAcct, err := c.db.Account(form.Host)
if err != nil {
return err
}
@@ -1015,8 +1019,14 @@ func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
}
}()
+ var success bool
dc.acct.authMtx.Lock()
- defer dc.acct.authMtx.Unlock()
+ defer func() {
+ dc.acct.authMtx.Unlock()
+ if success {
+ c.notify(newBondAuthUpdate(dc.acct.host, c.exchangeAuth(dc)))
+ }
+ }()
if !dc.acct.isAuthed {
return errors.New("login or register first")
@@ -1025,7 +1035,6 @@ func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
// Revert to initial values if we encounter any error below.
bondAssetID0 = dc.acct.bondAsset
targetTier0, maxBondedAmt0, penaltyComps0 = dc.acct.targetTier, dc.acct.maxBondedAmt, dc.acct.penaltyComps
- var success bool
defer func() { // still under authMtx lock on defer stack
if !success {
dc.acct.bondAsset = bondAssetID0
@@ -1054,7 +1063,10 @@ func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
dbAcct.TargetTier = targetTier
}
- penaltyComps := form.PenaltyComps
+ var penaltyComps = penaltyComps0
+ if form.PenaltyComps != nil {
+ penaltyComps = *form.PenaltyComps
+ }
dc.acct.penaltyComps = penaltyComps
dbAcct.PenaltyComps = penaltyComps
@@ -1169,6 +1181,7 @@ func (c *Core) UpdateBondOptions(form *BondOptionsForm) error {
success = true
} // else we might have already done ReserveBondFunds...
return err
+
}
// BondsFeeBuffer suggests how much extra may be required for the transaction
@@ -1530,7 +1543,7 @@ func (c *Core) makeAndPostBond(dc *dexConnection, acctExists bool, wallet *xcWal
details := fmt.Sprintf("Waiting for %d confirmations to post bond %v (%s) to %s",
reqConfs, bondCoinStr, unbip(bond.AssetID), dc.acct.host) // TODO: subject, detail := c.formatDetails(...)
c.notify(newBondPostNoteWithConfirmations(TopicBondConfirming, string(TopicBondConfirming),
- details, db.Success, bond.AssetID, bondCoinStr, 0, dc.acct.host))
+ details, db.Success, bond.AssetID, bondCoinStr, 0, dc.acct.host, c.exchangeAuth(dc)))
// Set up the coin waiter, which watches confirmations so the user knows
// when to expect their account to be marked paid by the server.
c.monitorBondConfs(dc, bond, reqConfs)
@@ -1591,7 +1604,8 @@ func (c *Core) bondConfirmed(dc *dexConnection, assetID uint32, coinID []byte, p
}
c.log.Infof("Bond %s (%s) confirmed.", bondIDStr, unbip(assetID))
details := fmt.Sprintf("New tier = %d (target = %d).", effectiveTier, targetTier) // TODO: format to subject,details
- c.notify(newBondPostNoteWithTier(TopicBondConfirmed, string(TopicBondConfirmed), details, db.Success, dc.acct.host, bondedTier))
+
+ c.notify(newBondPostNoteWithTier(TopicBondConfirmed, string(TopicBondConfirmed), details, db.Success, dc.acct.host, bondedTier, c.exchangeAuth(dc)))
} else if !foundConfirmed {
c.log.Errorf("bondConfirmed: Bond %s (%s) not found", bondIDStr, unbip(assetID))
// just try to authenticate...
@@ -1617,7 +1631,7 @@ func (c *Core) bondConfirmed(dc *dexConnection, assetID uint32, coinID []byte, p
details := fmt.Sprintf("New tier = %d", effectiveTier) // TODO: format to subject,details
c.notify(newBondPostNoteWithTier(TopicAccountRegistered, string(TopicAccountRegistered),
- details, db.Success, dc.acct.host, bondedTier)) // possibly redundant with SubjectBondConfirmed
+ details, db.Success, dc.acct.host, bondedTier, c.exchangeAuth(dc))) // possibly redundant with SubjectBondConfirmed
return nil
}
@@ -1669,7 +1683,7 @@ func (c *Core) bondExpired(dc *dexConnection, assetID uint32, coinID []byte, not
if int64(targetTier) > effectiveTier {
details := fmt.Sprintf("New tier = %d (target = %d).", effectiveTier, targetTier)
c.notify(newBondPostNoteWithTier(TopicBondExpired, string(TopicBondExpired),
- details, db.WarningLevel, dc.acct.host, bondedTier))
+ details, db.WarningLevel, dc.acct.host, bondedTier, c.exchangeAuth(dc)))
}
return nil
diff --git a/client/core/core.go b/client/core/core.go
index 89c95219d0..19d753276c 100644
--- a/client/core/core.go
+++ b/client/core/core.go
@@ -339,6 +339,7 @@ func coreMarketFromMsgMarket(dc *dexConnection, msgMkt *msgjson.Market) *Market
QuoteID: quote.ID,
QuoteSymbol: quote.Symbol,
LotSize: msgMkt.LotSize,
+ ParcelSize: msgMkt.ParcelSize,
RateStep: msgMkt.RateStep,
EpochLen: msgMkt.EpochLen,
StartEpoch: msgMkt.StartEpoch,
@@ -519,7 +520,8 @@ func (c *Core) exchangeInfo(dc *dexConnection) *Exchange {
CandleDurs: cfg.BinSizes,
ViewOnly: dc.acct.isViewOnly(),
Auth: acctBondState.ExchangeAuth,
- // TODO: Bonds
+ MaxScore: cfg.MaxScore,
+ PenaltyThreshold: cfg.PenaltyThreshold,
// Legacy reg fee (V0PURGE)
RegFees: feeAssets,
diff --git a/client/core/core_test.go b/client/core/core_test.go
index 1c48872911..a030f6531c 100644
--- a/client/core/core_test.go
+++ b/client/core/core_test.go
@@ -250,6 +250,7 @@ func testDexConnection(ctx context.Context, crypter *tCrypter) (*dexConnection,
Base: tUTXOAssetA.ID,
Quote: tUTXOAssetB.ID,
LotSize: dcrBtcLotSize,
+ ParcelSize: 100,
RateStep: dcrBtcRateStep,
EpochLen: 60000,
MarketBuyBuffer: 1.1,
@@ -10575,7 +10576,7 @@ func TestUpdateBondOptions(t *testing.T) {
name: "set target tier to 1",
bal: singlyBondedReserves,
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTier,
BondAssetID: &bondAsset.ID,
},
@@ -10589,7 +10590,7 @@ func TestUpdateBondOptions(t *testing.T) {
name: "low balance",
bal: singlyBondedReserves - 1,
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTier,
BondAssetID: &bondAsset.ID,
},
@@ -10599,7 +10600,7 @@ func TestUpdateBondOptions(t *testing.T) {
name: "max-bonded too low",
bal: singlyBondedReserves,
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTier,
BondAssetID: &bondAsset.ID,
MaxBondedAmt: &tooLowMaxBonded,
@@ -10609,7 +10610,7 @@ func TestUpdateBondOptions(t *testing.T) {
{
name: "unsupported bond asset",
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTier,
BondAssetID: &wrongBondAssetID,
},
@@ -10619,7 +10620,7 @@ func TestUpdateBondOptions(t *testing.T) {
name: "lower target tier with zero balance OK",
bal: 0,
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTierZero,
BondAssetID: &bondAsset.ID,
},
@@ -10634,7 +10635,7 @@ func TestUpdateBondOptions(t *testing.T) {
name: "lower target tier to zero with other exchanges still keeps reserves",
bal: 0,
form: BondOptionsForm{
- Addr: acct.host,
+ Host: acct.host,
TargetTier: &targetTierZero,
BondAssetID: &bondAsset.ID,
},
@@ -10775,7 +10776,7 @@ func TestRotateBonds(t *testing.T) {
// if the locktime is not too soon.
acct.bonds = append(acct.bonds, acct.pendingBonds[0])
acct.pendingBonds = nil
- acct.bonds[0].LockTime = mergeableLocktimeThresh + 1
+ acct.bonds[0].LockTime = mergeableLocktimeThresh + 5
rig.queuePrevalidateBond()
run(1, 0, 2*bondAsset.Amt+bondFeeBuffer)
mergingBond := acct.pendingBonds[0]
diff --git a/client/core/exchangeratefetcher.go b/client/core/exchangeratefetcher.go
index b943452768..68c800ea49 100644
--- a/client/core/exchangeratefetcher.go
+++ b/client/core/exchangeratefetcher.go
@@ -35,7 +35,7 @@ const (
var (
dcrDataURL = "https://explorer.dcrdata.org/api/exchangerate"
// coinpaprika has two options. /tickers is for the top 2500 assets all in
- // one request. /ticker/[slug] is for a single ticker. From testing
+ // one request. /tickers/[slug] is for a single ticker. From testing
// Single ticker request took 274.626125ms
// Size of single ticker response: 0.733 kB
// All tickers request took 47.651851ms
@@ -48,7 +48,7 @@ var (
// So any more than 25000 / 3600 = 6.9 assets, and we can expect to run into
// rate limits. But the bandwidth of the full tickers request is kinda
// ridiculous too. Solution needed.
- coinpaprikaURL = "https://api.coinpaprika.com/v1/tickers/%s"
+ coinpaprikaURL = "https://api.coinpaprika.com/v1/tickers"
// The best info I can find on Messari says
// Without an API key requests are rate limited to 20 requests per minute
// and 1000 requests per day.
@@ -142,26 +142,12 @@ func newCommonRateSource(fetcher rateFetcher) *commonRateSource {
// for sample request and response information.
func FetchCoinpaprikaRates(ctx context.Context, log dex.Logger, assets map[uint32]*SupportedAsset) map[uint32]float64 {
fiatRates := make(map[uint32]float64)
- fetchRate := func(sa *SupportedAsset) {
- assetID := sa.ID
- if sa.Wallet == nil {
- // we don't want to fetch rates for assets with no wallet.
- return
- }
-
- res := new(struct {
- Quotes struct {
- Currency struct {
- Price float64 `json:"price"`
- } `json:"USD"`
- } `json:"quotes"`
- })
-
+ slugAssets := make(map[string]uint32)
+ for _, sa := range assets {
symbol := dex.TokenSymbol(sa.Symbol)
if symbol == "dextt" {
- return
+ continue
}
-
name := sa.Name
// TODO: Store these within the *SupportedAsset.
switch symbol {
@@ -171,21 +157,37 @@ func FetchCoinpaprikaRates(ctx context.Context, log dex.Logger, assets map[uint3
symbol = "matic"
name = "polygon"
}
+ slug := coinpapSlug(symbol, name)
+ slugAssets[slug] = sa.ID
+ }
- reqStr := fmt.Sprintf(coinpaprikaURL, coinpapSlug(symbol, name))
-
- ctx, cancel := context.WithTimeout(ctx, fiatRequestTimeout)
- defer cancel()
+ ctx, cancel := context.WithTimeout(ctx, fiatRequestTimeout)
+ defer cancel()
- if err := getRates(ctx, reqStr, res); err != nil {
- log.Errorf("Error getting fiat exchange rates from coinpaprika: %v", err)
- return
- }
+ var res []*struct {
+ ID string `json:"id"`
+ Quotes struct {
+ USD struct {
+ Price float64 `json:"price"`
+ } `json:"USD"`
+ } `json:"quotes"`
+ }
- fiatRates[assetID] = res.Quotes.Currency.Price
+ if err := getRates(ctx, coinpaprikaURL, &res); err != nil {
+ log.Errorf("Error getting fiat exchange rates from coinpaprika: %v", err)
+ return fiatRates
}
- for _, sa := range assets {
- fetchRate(sa)
+ for _, coinInfo := range res {
+ assetID, found := slugAssets[coinInfo.ID]
+ if !found {
+ continue
+ }
+ price := coinInfo.Quotes.USD.Price
+ if price == 0 {
+ log.Errorf("zero-price returned from coinpaprika for slug %s", coinInfo.ID)
+ continue
+ }
+ fiatRates[assetID] = price
}
return fiatRates
}
@@ -288,6 +290,6 @@ func getRates(ctx context.Context, url string, thing any) error {
return fmt.Errorf("error %d fetching %q", resp.StatusCode, url)
}
- reader := io.LimitReader(resp.Body, 1<<20)
+ reader := io.LimitReader(resp.Body, 1<<22)
return json.NewDecoder(reader).Decode(thing)
}
diff --git a/client/core/notification.go b/client/core/notification.go
index cb5bbf3721..83b6b9111a 100644
--- a/client/core/notification.go
+++ b/client/core/notification.go
@@ -265,14 +265,19 @@ func newBondRefundNote(topic Topic, subject, details string, severity db.Severit
}
}
+const (
+ TopicBondAuthUpdate Topic = "BondAuthUpdate"
+)
+
// BondPostNote is a notification regarding bond posting.
type BondPostNote struct {
db.Notification
- Asset *uint32 `json:"asset,omitempty"`
- Confirmations *int32 `json:"confirmations,omitempty"`
- BondedTier *int64 `json:"bondedTier,omitempty"`
- CoinID *string `json:"coinID,omitempty"`
- Dex string `json:"dex,omitempty"`
+ Asset *uint32 `json:"asset,omitempty"`
+ Confirmations *int32 `json:"confirmations,omitempty"`
+ BondedTier *int64 `json:"bondedTier,omitempty"`
+ CoinID *string `json:"coinID,omitempty"`
+ Dex string `json:"dex,omitempty"`
+ Auth *ExchangeAuth `json:"auth,omitempty"`
}
func newBondPostNote(topic Topic, subject, details string, severity db.Severity, dexAddr string) *BondPostNote {
@@ -283,20 +288,39 @@ func newBondPostNote(topic Topic, subject, details string, severity db.Severity,
}
}
-func newBondPostNoteWithConfirmations(topic Topic, subject, details string, severity db.Severity, asset uint32, coinID string, currConfs int32, dexAddr string) *BondPostNote {
- bondPmtNt := newBondPostNote(topic, subject, details, severity, dexAddr)
+func newBondPostNoteWithConfirmations(
+ topic Topic,
+ subject string,
+ details string,
+ severity db.Severity,
+ asset uint32,
+ coinID string,
+ currConfs int32,
+ host string,
+ auth *ExchangeAuth,
+) *BondPostNote {
+
+ bondPmtNt := newBondPostNote(topic, subject, details, severity, host)
bondPmtNt.Asset = &asset
bondPmtNt.CoinID = &coinID
bondPmtNt.Confirmations = &currConfs
+ bondPmtNt.Auth = auth
return bondPmtNt
}
-func newBondPostNoteWithTier(topic Topic, subject, details string, severity db.Severity, dexAddr string, bondedTier int64) *BondPostNote {
+func newBondPostNoteWithTier(topic Topic, subject, details string, severity db.Severity, dexAddr string, bondedTier int64, auth *ExchangeAuth) *BondPostNote {
bondPmtNt := newBondPostNote(topic, subject, details, severity, dexAddr)
bondPmtNt.BondedTier = &bondedTier
+ bondPmtNt.Auth = auth
return bondPmtNt
}
+func newBondAuthUpdate(host string, auth *ExchangeAuth) *BondPostNote {
+ n := newBondPostNote(TopicBondAuthUpdate, "", "", db.Data, host)
+ n.Auth = auth
+ return n
+}
+
// SendNote is a notification regarding a requested send or withdraw.
type SendNote struct {
db.Notification
@@ -673,8 +697,8 @@ func newWalletNote(n asset.WalletNotification) *WalletNote {
type ReputationNote struct {
db.Notification
- Host string
- Reputation account.Reputation
+ Host string `json:"host"`
+ Reputation account.Reputation `json:"rep"`
}
const TopicReputationUpdate = "ReputationUpdate"
diff --git a/client/core/types.go b/client/core/types.go
index 7b6155fc18..ea21e8bc80 100644
--- a/client/core/types.go
+++ b/client/core/types.go
@@ -188,10 +188,10 @@ type SupportedAsset struct {
// BondOptionsForm is used from the settings page to change the auto-bond
// maintenance setting for a DEX.
type BondOptionsForm struct {
- Addr string `json:"host"`
+ Host string `json:"host"`
TargetTier *uint64 `json:"targetTier,omitempty"`
MaxBondedAmt *uint64 `json:"maxBondedAmt,omitempty"`
- PenaltyComps uint16 `json:"penaltyComps"`
+ PenaltyComps *uint16 `json:"penaltyComps,omitempty"`
BondAssetID *uint32 `json:"bondAssetID,omitempty"`
}
@@ -525,6 +525,7 @@ type Market struct {
QuoteID uint32 `json:"quoteid"`
QuoteSymbol string `json:"quotesymbol"`
LotSize uint64 `json:"lotsize"`
+ ParcelSize uint32 `json:"parcelsize"`
RateStep uint64 `json:"ratestep"`
EpochLen uint64 `json:"epochlen"`
StartEpoch uint64 `json:"startepoch"`
@@ -693,7 +694,8 @@ type Exchange struct {
CandleDurs []string `json:"candleDurs"`
ViewOnly bool `json:"viewOnly"`
Auth ExchangeAuth `json:"auth"`
- // TODO: Bonds slice(s) - and a LockedInBonds(assetID) method
+ PenaltyThreshold uint32 `json:"penaltyThreshold"`
+ MaxScore uint32 `json:"maxScore"`
// OLD fields for the legacy registration fee (V0PURGE):
RegFees map[string]*FeeAsset `json:"regFees"`
diff --git a/client/rpcserver/types.go b/client/rpcserver/types.go
index 4dab0a2432..fb7a7ef109 100644
--- a/client/rpcserver/types.go
+++ b/client/rpcserver/types.go
@@ -507,7 +507,7 @@ func parseBondOptsArgs(params *RawParams) (*core.BondOptionsForm, error) {
}
}
- var penaltyComps uint16
+ var penaltyComps *uint16
if len(params.Args) > 4 {
pc, err := checkIntArg(params.Args[4], "penaltyComps", 16)
if err != nil {
@@ -517,12 +517,13 @@ func parseBondOptsArgs(params *RawParams) (*core.BondOptionsForm, error) {
return nil, fmt.Errorf("penaltyComps out of range (0, %d)", math.MaxUint16)
}
if pc > 0 {
- penaltyComps = uint16(pc)
+ pc16 := uint16(pc)
+ penaltyComps = &pc16
}
}
req := &core.BondOptionsForm{
- Addr: params.Args[0],
+ Host: params.Args[0],
TargetTier: targetTierP,
MaxBondedAmt: maxBondedP,
BondAssetID: bondAssetP,
diff --git a/client/webserver/locales/ar.go b/client/webserver/locales/ar.go
index b7517ce9e8..1e7a182da4 100644
--- a/client/webserver/locales/ar.go
+++ b/client/webserver/locales/ar.go
@@ -178,7 +178,6 @@ var Ar = map[string]string{
"All markets at": "جميع الأسواق في",
"pick a different asset": "اختر أصلًا مختلفًا",
"Create": "انشاء",
- "Register_loudly": "التسجيل!",
"1 Sync the Blockchain": "1: مزامنة سلسلة الكتل",
"Progress": "قيد التنفيذ",
"remaining": "الوقت المتبقي",
diff --git a/client/webserver/locales/de-de.go b/client/webserver/locales/de-de.go
index a4e669b8a9..2807134eca 100644
--- a/client/webserver/locales/de-de.go
+++ b/client/webserver/locales/de-de.go
@@ -169,11 +169,9 @@ var DeDE = map[string]string{
"Export Trades": "Exportiere Trades",
"change the wallet type": "den Wallet-Typ ändern",
"confirmations": "Bestätigungen",
- "how_reg": "Wie soll die Anmeldegebühr bezahlt werden?",
"All markets at": "Alle Märkte bei",
"pick a different asset": "ein anderes Asset wählen",
"Create": "Erstellen",
- "Register_loudly": "Registrieren!",
"1 Sync the Blockchain": "1: Blockchain synchronisieren",
"Progress": "Fortschritt",
"remaining": "verbleibend",
diff --git a/client/webserver/locales/en-us.go b/client/webserver/locales/en-us.go
index 49a6c6d9f2..a35e5b03cc 100644
--- a/client/webserver/locales/en-us.go
+++ b/client/webserver/locales/en-us.go
@@ -28,13 +28,17 @@ var EnUS = map[string]string{
"Skip Registration": "No account (view-only mode)",
"Confirm Registration": "Confirm Registration and Bonding",
"app_pw_reg": "Enter your app password to confirm DEX registration and bond creation.",
- "reg_confirm_submit": `When you submit this form, funds will be spent from your wallet to post a fidelity bond, which is redeemable by you in the future.`,
+ "reg_confirm_submit": `When you submit this form, funds from your wallet will be temporarily locked into a fidelity bond contract, which is redeemable by you in the future.`,
"bond_strength": "Bond Strength",
- "update_bond_options": "Update Bond Options",
- "bond_options": "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 (do not post new bonds).",
+ "compensation_tooltip": "Enable posting additional bonds to offset penalized tiers.",
+ "Actual Tier": "Actual Tier",
+ "Penalties": "Penalties",
+ "Change Tier": "Change Tier",
+ "Limit Bonus": "Limit Bonus",
+ "Score": "Score",
+ "Confirm Bond Options": "Confirm Bond Options",
"provided_markets": "This DEX provides the following markets:",
"accepted_fee_assets": "This DEX recognizes the bond assets:",
"base_header": "Base",
@@ -195,22 +199,32 @@ var EnUS = map[string]string{
"Export Trades": "Export Trades",
"change the wallet type": "change the wallet type",
"confirmations": "confirmations",
- "how_reg": "How will you create your bond?",
"All markets at": "All markets at",
"pick a different asset": "pick a different asset",
"Create": "Create",
- "Register_loudly": "Register!",
"1 Sync the Blockchain": "1: Sync the Blockchain",
"Progress": "Progress",
"remaining": "remaining",
"2 Fund your Wallet": "2: Fund your Wallet",
- "whatsabond": "Fidelity bonds are time-locked funds redeemable only by you, but in the future. This is meant to combat disruptive behavior like backing out on swaps.",
+ "bond_definition": "A fidelity bond is funds temporarily locked in an on-chain contract. After the contract expires, your wallet will reclaim the funds. On mainnet, funds are locked for 2 months.",
+ "bonds_can_be_revoked": "Bonds can be revoked if an account engages in continued disruptive behavior, such as backing out on a swap. Revoked bonds can be re-activated with continued normal trading activity.",
+ "bigger_bonds_higher_limit": "You can create larger bonds to increase your trading tier, enabling trading of larger quantities at a time. Larger bonds also increase your capacity for violations before trading privileges are suspended.",
+ "limits_reputation": "Trading limits are also increased as you establish reputation by engaging in normal trading activity and successfully completing matches.",
+ "wallet_bond_reserves": "Your wallet will automatically reserve the funds necessary to keep you bonded at your selected trading tier, and will broadcast new bonds to replace expiring ones. You can lower or raise your trading tier in the exchange's settings panel. Set your trading tier to zero to disable your account (once your existing bonds expire).",
+ "Got it": "Got it",
+ "Trading Limits": "Trading Limits",
+ "What is a fidelity bond": "What is a fidelity bond?",
+ "order_form_remaining_limit": ` lots remaining in tier trading limit`,
+ "Parcel Size": "Parcel Size",
+ "Trading Limit": "Trading Limit",
+ "Current Usage": "Current Usage",
+ "score_factors": "Increase your score by successfully completing trades. Failure to act on a trade will decrease your score.",
"Bond amount": "Bond amount",
"Reserves for tx fees": "Funds to reserve for transaction fees to maintain your bonds",
"Tx Fee Balance": "Transaction Fee Balance:",
"Your Deposit Address": "Your Wallet's Deposit Address",
"Send enough for bonds": `Make sure you send enough to also cover network fees. You may deposit as much as you like to your wallet, since only the bond amount will be used in the next step. The deposit must confirm to proceed.`,
- "Send enough with estimate": `Deposit at least XYZ to cover network fees and overlap periods when a bond is expired (but waiting for refund) and another must be posted. You may deposit as much as you like to your wallet, since only the required amount will be used in the next step. The deposit must confirm to proceed.`,
+ "Send enough with estimate": `Deposit at least XYZ to cover your bond and fees. You may deposit as much as you like to your wallet, since only the required amount will be used in the next step. The wallet may require a confirmation on the new funds before proceeding.`,
"Send funds for token": `Deposit at least XYZ and XYZ to also cover fees. You may deposit as much as you like to your wallet, since only the required amount will be used in the next step. The deposit must confirm to proceed.`,
"add a different server": "add a different server",
"Add a custom server": "Add a custom server",
@@ -276,6 +290,16 @@ var EnUS = map[string]string{
"Settings": "Settings",
"asset_name Markets": " Markets",
"Host": "Host",
+ "Trading Tier": "Trading Tier",
+ "Bond Lock": "Bond Lock",
+ "USD": "USD",
+ "Fee Reserves": "Fee Reserves",
+ "Select your bond asset": "Select your bond asset",
+ "choose a different asset": "choose a different asset",
+ "current_bonding_asset": `Using for bonding`,
+ "Choose your trading tier": "Choose your trading tier",
+ "trading_tier_message": "Increase your trading tier to enable trading of larger amounts. Trading limits also grow with reputation.",
+ "Other Trading Limits": "Other Trading Limits",
"No Recent Activity": "No Recent Activity",
"Recent asset_name Activity": "Recent Activity",
"other_actions": "Other Actions",
@@ -433,15 +457,8 @@ var EnUS = map[string]string{
"fiat_rates": "Fiat Rates",
"market_making_running": "Market making is running",
"cannot_manually_trade": "You cannot manually place orders while market making is running",
- "bond_details": "Bond Details",
- "current_tier": "Current Tier",
- "current_tier_tooltip": "Number of active bonds that have not yet reached the expiry threshold as reported by the DEX server. Increase your target tier to raise your account tier, boost your trading limits, and offset penalties, if any.",
- "current_target_tier_tooltip": "This is the target account tier you wish to maintain. If zero, bond maintenance will be disabled and new bonds will not be posted.",
- "current_target_tier": "Current Target Tier",
- "bond_cost": "Bond Cost",
- "bond_cost_tooltip": "Cost of a single bond without fees and bond maintenance fund reservation.",
- "bond_reservations": "Bond Reservation",
- "bond_reservations_tooltip": "Total funds that will be locked when you post a bond to cover fees and bond maintenance costs.",
+ "back": "Back",
+ "current_tier_tooltip": "Tier represented by active bonds. Increase your target tier to raise your target tier, boost your trading limits, and offset penalties, if any.",
"Reset App Password": "Reset App Password",
"reset_app_pw_msg": "Reset your app password using your app seed. If you provide the correct app seed, you can login again with the new password.",
"Forgot Password": "Forgot Password?",
diff --git a/client/webserver/locales/pl-pl.go b/client/webserver/locales/pl-pl.go
index cb20991119..781a32dc95 100644
--- a/client/webserver/locales/pl-pl.go
+++ b/client/webserver/locales/pl-pl.go
@@ -168,7 +168,6 @@ var PlPL = map[string]string{
"All markets at": "Wszystkie rynki na",
"pick a different asset": "wybierz inne aktywo",
"Create": "Utwórz",
- "Register_loudly": "Zarejestruj!",
"1 Sync the Blockchain": "1: Zsynchronizuj blockchain",
"Progress": "Postęp",
"remaining": "pozostało",
diff --git a/client/webserver/locales/pt-br.go b/client/webserver/locales/pt-br.go
index 7a7aba9715..beebf5e96c 100644
--- a/client/webserver/locales/pt-br.go
+++ b/client/webserver/locales/pt-br.go
@@ -169,7 +169,6 @@ var PtBr = map[string]string{
"All markets at": "Todos mercados",
"pick a different asset": "Escolher ativo diferente",
"Create": "Criar",
- "Register_loudly": "Registre!",
"1 Sync the Blockchain": "1: Sincronizar a Blockchain",
"Progress": "Progresso",
"remaining": "Faltando",
diff --git a/client/webserver/locales/zh-cn.go b/client/webserver/locales/zh-cn.go
index 71f8411a99..ac9894fee2 100644
--- a/client/webserver/locales/zh-cn.go
+++ b/client/webserver/locales/zh-cn.go
@@ -171,7 +171,6 @@ var ZhCN = map[string]string{
"All markets at": "所有市场",
"pick a different asset": "选择其它的资产",
"Create": "创建",
- "Register_loudly": "注册!",
"1 Sync the Blockchain": "1: 同步区块链",
"Progress": "进度",
"remaining": "剩余",
diff --git a/client/webserver/site/src/css/dex_settings.scss b/client/webserver/site/src/css/dex_settings.scss
index e114c4a09a..e930ebd150 100644
--- a/client/webserver/site/src/css/dex_settings.scss
+++ b/client/webserver/site/src/css/dex_settings.scss
@@ -6,3 +6,7 @@
color: green;
}
+#penaltyCompInput {
+ width: 2rem;
+}
+
diff --git a/client/webserver/site/src/css/forms.scss b/client/webserver/site/src/css/forms.scss
index 0c29b24f44..f66eb820fe 100644
--- a/client/webserver/site/src/css/forms.scss
+++ b/client/webserver/site/src/css/forms.scss
@@ -1,18 +1,5 @@
#regAssetForm {
- #whatsabond {
- max-width: 425px;
- }
-
- div.reg-asset-allmkts {
- min-width: 210px;
- max-width: 320px;
- }
-
div.reg-asset {
- min-width: 425px;
- padding: 20px 10px;
- border-bottom: dashed 2px #7777;
-
.fader {
position: absolute;
bottom: 0;
@@ -44,11 +31,6 @@
}
}
- img.reg-asset-logo {
- width: 50px;
- height: 50px;
- }
-
img.reg-market-logo {
width: 14px;
height: 14px;
@@ -59,7 +41,7 @@
@extend .stylish-overflow;
display: block;
- max-height: 65px;
+ max-height: 120px;
line-height: 1.15;
overflow-y: hidden;
margin-right: 8px;
@@ -83,13 +65,6 @@
}
}
- div.reg-asset-details {
- box-sizing: content-box;
- line-height: 1.25;
- width: 100px;
- padding: 0 50px 0 25px;
- }
-
div.reg-assets-markets-wrap {
position: relative;
@@ -102,6 +77,25 @@
color: #c7c3cc;
}
+ .reg-asset-table {
+ thead > tr > th {
+ border-top: 1px solid;
+ }
+
+ th,
+ td {
+ border-color: $light_border_color;
+ border-width: 1px;
+ border-style: none solid solid;
+ padding: 5px;
+ text-align: left;
+ }
+ }
+
+ input[data-tmpl=regAssetTier] {
+ width: 3em;
+ }
+
.readygreen {
color: #009931;
}
@@ -125,11 +119,6 @@
}
}
- img.logo {
- width: 30px;
- height: 30px;
- }
-
input.app-pass {
// margin: 0 auto;
display: inline-block;
@@ -143,6 +132,10 @@
div.borderright {
border-right: 1px solid #777;
}
+
+ .mw50 {
+ max-width: 50%;
+ }
}
#newWalletForm {
@@ -275,11 +268,6 @@ div[data-handler=register] {
width: 25px;
}
- .borderleft {
- padding-left: 25px;
- border-left: solid 1px #777;
- }
-
.logo {
width: 40px;
height: 40px;
@@ -339,8 +327,7 @@ div[data-handler=register] {
#vSendForm,
#exportSeedAuth,
#cancelForm,
-#quickConfigForm,
-#bondDetailsForm {
+#quickConfigForm {
width: 375px;
}
@@ -422,9 +409,78 @@ a[data-tmpl=walletCfgGuide] {
}
}
+div[data-tmpl=scoreTray] {
+ background-color: $buycolor_dark;
+ height: 12px;
+ border-radius: 100px;
+ overflow: hidden;
+
+ div[data-tmpl=scoreWarn] {
+ background-color: $sellcolor_dark;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ }
+}
+
+span[data-tmpl=scorePointer] {
+ transform: translateX(-50%);
+
+ div[data-tmpl=scoreData] {
+ top: 0;
+ bottom: 0;
+
+ &.positive {
+ right: 150%;
+ }
+
+ &.negative {
+ left: 150%;
+ }
+ }
+}
+
+.penalty-marker {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 10%;
+ width: 2px;
+ z-index: 2;
+ background-color: black;
+}
+
div[data-handler=init] {
.quickconfig-asset-logo {
width: 25px;
height: 25px;
}
}
+
+.anitoggle {
+ width: 1.5rem;
+ height: 0.9rem;
+ border-radius: 0.45rem;
+ background-color: #777a;
+ cursor: pointer;
+
+ &.on {
+ background-color: $buycolor_dark;
+ }
+
+ & > div {
+ position: relative;
+ top: 0.1rem;
+ left: 0.1rem;
+ width: 0.7rem;
+ height: 0.7rem;
+ border-radius: 0.35rem;
+ transition: left 0.5s;
+ background-color: $dark_body_bg;
+ }
+
+ &.on > div {
+ left: 0.7rem;
+ }
+}
\ No newline at end of file
diff --git a/client/webserver/site/src/css/forms_dark.scss b/client/webserver/site/src/css/forms_dark.scss
index 2adc2b6f77..dc11f48a80 100644
--- a/client/webserver/site/src/css/forms_dark.scss
+++ b/client/webserver/site/src/css/forms_dark.scss
@@ -31,6 +31,12 @@ body.dark {
}
}
}
+
+ .reg-asset-table {
+ th, td {
+ border-color: $dark_border_color;
+ }
+ }
}
::-webkit-calendar-picker-indicator {
diff --git a/client/webserver/site/src/css/main.scss b/client/webserver/site/src/css/main.scss
index c64525a626..844a69e208 100644
--- a/client/webserver/site/src/css/main.scss
+++ b/client/webserver/site/src/css/main.scss
@@ -445,7 +445,7 @@ div.popup-notes {
}
hr.dashed {
- border-top: 1px dashed #777;
+ border-top: dashed 2px #777;
}
.vscroll {
diff --git a/client/webserver/site/src/css/market.scss b/client/webserver/site/src/css/market.scss
index b34c804d06..6b823b01de 100644
--- a/client/webserver/site/src/css/market.scss
+++ b/client/webserver/site/src/css/market.scss
@@ -585,7 +585,7 @@ div[data-handler=markets] {
&.selected {
opacity: 1;
- background-color: #e8ebed;
+ background-color: #0001;
div.opt-check {
background-color: #2cce9c;
diff --git a/client/webserver/site/src/css/market_dark.scss b/client/webserver/site/src/css/market_dark.scss
index 765bb373f2..81d3d57336 100644
--- a/client/webserver/site/src/css/market_dark.scss
+++ b/client/webserver/site/src/css/market_dark.scss
@@ -87,8 +87,6 @@ body.dark {
}
#orderForm {
- color: #a1a1a1;
-
button {
color: #aaa;
}
@@ -137,7 +135,7 @@ body.dark {
}
.order-opt.selected {
- background-color: #222e38;
+ background-color: #fff1;
}
}
diff --git a/client/webserver/site/src/css/settings.scss b/client/webserver/site/src/css/settings.scss
index 360977ddc1..8c27894c6f 100644
--- a/client/webserver/site/src/css/settings.scss
+++ b/client/webserver/site/src/css/settings.scss
@@ -1,11 +1,10 @@
div.settings {
- display: inline-block;
- width: 500px;
- text-align: left;
+ min-width: 375px;
& > div {
- position: relative;
- padding: 10px;
+ width: 100%;
+ text-align: left;
+ padding: 10px 0;
border-bottom: 1px solid #7777;
}
@@ -13,8 +12,8 @@ div.settings {
border-top: 1px solid #7777;
}
- & > div.form-check {
- padding-left: 35px;
+ div.form-check {
+ padding-left: 25px;
}
button {
diff --git a/client/webserver/site/src/html/dexsettings.tmpl b/client/webserver/site/src/html/dexsettings.tmpl
index fded08256a..f02214247f 100644
--- a/client/webserver/site/src/html/dexsettings.tmpl
+++ b/client/webserver/site/src/html/dexsettings.tmpl
@@ -1,35 +1,86 @@
{{define "dexsettings"}}
{{template "top" .}}
{{$passwordIsCached := .UserInfo.PasswordIsCached}}
-