diff --git a/server/public.go b/server/public.go
index 5c3f09ac..9edac987 100644
--- a/server/public.go
+++ b/server/public.go
@@ -30,6 +30,8 @@ const blocksOnPage = 50
const mempoolTxsOnPage = 50
const txsInAPI = 1000
+const secondaryCoinCookieName = "secondary_coin"
+
const (
_ = iota
apiV1
@@ -330,8 +332,8 @@ func (s *PublicServer) jsonHandler(handler func(r *http.Request, apiVersion int)
}
}
-func (s *PublicServer) newTemplateData() *TemplateData {
- return &TemplateData{
+func (s *PublicServer) newTemplateData(r *http.Request) *TemplateData {
+ t := &TemplateData{
CoinName: s.is.Coin,
CoinShortcut: s.is.CoinShortcut,
CoinLabel: s.is.CoinLabel,
@@ -339,10 +341,47 @@ func (s *PublicServer) newTemplateData() *TemplateData {
InternalExplorer: s.internalExplorer && !s.is.InitialSync,
TOSLink: api.Text.TOSLink,
}
+ if s.is.HasFiatRates {
+ // get the secondary coin and if it should be shown either from query parameters "secondary" and "use_secondary"
+ // or from the cookie "secondary_coin" in the format secondary=use_secondary, for example EUR=true
+ // the query parameters take precedence over the cookie
+ var cookieSecondary string
+ var cookieUseSecondary bool
+ cookie, _ := r.Cookie(secondaryCoinCookieName)
+ if cookie != nil {
+ a := strings.Split(cookie.Value, "=")
+ if len(a) == 2 {
+ cookieSecondary = a[0]
+ cookieUseSecondary, _ = strconv.ParseBool(a[1])
+ }
+ }
+ secondary := strings.ToLower(r.URL.Query().Get("secondary"))
+ if secondary == "" {
+ if cookieSecondary != "" {
+ secondary = strings.ToLower(cookieSecondary)
+ } else {
+ secondary = "usd"
+ }
+ }
+ ticker := s.is.GetCurrentTicker(secondary, "")
+ if ticker == nil && secondary != "usd" {
+ secondary = "usd"
+ ticker = s.is.GetCurrentTicker(secondary, "")
+ }
+ if ticker != nil {
+ t.SecondaryCoin = strings.ToUpper(secondary)
+ t.CurrentSecondaryCoinRate = float64(ticker.Rates[secondary])
+ t.UseSecondaryCoin, _ = strconv.ParseBool(r.URL.Query().Get("use_secondary"))
+ if !t.UseSecondaryCoin {
+ t.UseSecondaryCoin = cookieUseSecondary
+ }
+ }
+ }
+ return t
}
-func (s *PublicServer) newTemplateDataWithError(text string) *TemplateData {
- td := s.newTemplateData()
+func (s *PublicServer) newTemplateDataWithError(text string, r *http.Request) *TemplateData {
+ td := s.newTemplateData(r)
td.Error = &api.APIError{Text: text}
return td
}
@@ -359,9 +398,9 @@ func (s *PublicServer) htmlTemplateHandler(handler func(w http.ResponseWriter, r
debug.PrintStack()
t = errorInternalTpl
if s.debug {
- data = s.newTemplateDataWithError(fmt.Sprint("Internal server error: recovered from panic ", e))
+ data = s.newTemplateDataWithError(fmt.Sprint("Internal server error: recovered from panic ", e), r)
} else {
- data = s.newTemplateDataWithError("Internal server error")
+ data = s.newTemplateDataWithError("Internal server error", r)
}
}
// noTpl means the handler completely handled the request
@@ -387,7 +426,7 @@ func (s *PublicServer) htmlTemplateHandler(handler func(w http.ResponseWriter, r
if err != nil || (data == nil && t != noTpl) {
t = errorInternalTpl
if apiErr, ok := err.(*api.APIError); ok {
- data = s.newTemplateData()
+ data = s.newTemplateData(r)
data.Error = apiErr
if apiErr.Public {
t = errorTpl
@@ -397,12 +436,16 @@ func (s *PublicServer) htmlTemplateHandler(handler func(w http.ResponseWriter, r
glog.Error(handlerName, " error: ", err)
}
if s.debug {
- data = s.newTemplateDataWithError(fmt.Sprintf("Internal server error: %v, data %+v", err, data))
+ data = s.newTemplateDataWithError(fmt.Sprintf("Internal server error: %v, data %+v", err, data), r)
} else {
- data = s.newTemplateDataWithError("Internal server error")
+ data = s.newTemplateDataWithError("Internal server error", r)
}
}
}
+ // if SecondaryCoin is specified, set secondary_coin cookie
+ if data != nil && data.SecondaryCoin != "" {
+ http.SetCookie(w, &http.Cookie{Name: secondaryCoinCookieName, Value: data.SecondaryCoin + "=" + strconv.FormatBool(data.UseSecondaryCoin), Path: "/"})
+ }
}
}
@@ -427,31 +470,37 @@ const (
// TemplateData is used to transfer data to the templates
type TemplateData struct {
- CoinName string
- CoinShortcut string
- CoinLabel string
- InternalExplorer bool
- ChainType bchain.ChainType
- Address *api.Address
- AddrStr string
- Tx *api.Tx
- Error *api.APIError
- Blocks *api.Blocks
- Block *api.Block
- Info *api.SystemInfo
- MempoolTxids *api.MempoolTxids
- Page int
- PrevPage int
- NextPage int
- PagingRange []int
- PageParams template.URL
- TOSLink string
- SendTxHex string
- Status string
- NonZeroBalanceTokens bool
- TokenId string
- URI string
- ContractInfo *bchain.ContractInfo
+ CoinName string
+ CoinShortcut string
+ CoinLabel string
+ InternalExplorer bool
+ ChainType bchain.ChainType
+ Address *api.Address
+ AddrStr string
+ Tx *api.Tx
+ Error *api.APIError
+ Blocks *api.Blocks
+ Block *api.Block
+ Info *api.SystemInfo
+ MempoolTxids *api.MempoolTxids
+ Page int
+ PrevPage int
+ NextPage int
+ PagingRange []int
+ PageParams template.URL
+ TOSLink string
+ SendTxHex string
+ Status string
+ NonZeroBalanceTokens bool
+ TokenId string
+ URI string
+ ContractInfo *bchain.ContractInfo
+ SecondaryCoin string
+ UseSecondaryCoin bool
+ CurrentSecondaryCoinRate float64
+ TxBlocktime int64
+ TxDate string
+ TxBlocktimeSecondaryCoinRate float64
}
func (s *PublicServer) parseTemplates() []*template.Template {
@@ -460,6 +509,7 @@ func (s *PublicServer) parseTemplates() []*template.Template {
"formatUnixTime": formatUnixTime,
"formatAmount": s.formatAmount,
"formatAmountWithDecimals": formatAmountWithDecimals,
+ "amount": s.amount,
"formatInt64": formatInt64,
"formatInt": formatInt,
"formatUint32": formatUint32,
@@ -605,8 +655,6 @@ func toJSON(data interface{}) string {
return string(json)
}
-// for now return the string as it is
-// in future could be used to do coin specific formatting
func (s *PublicServer) formatAmount(a *api.Amount) string {
if a == nil {
return "0"
@@ -621,6 +669,79 @@ func formatAmountWithDecimals(a *api.Amount, d int) string {
return a.DecimalString(d)
}
+func appendAmountSpan(rv *strings.Builder, class, amount, shortcut, txDate string) {
+ rv.WriteString(`")
+ i := strings.IndexByte(amount, '.')
+ if i < 0 {
+ appendSeparatedNumberSpans(rv, amount, "nc")
+ } else {
+ appendSeparatedNumberSpans(rv, amount[:i], "nc")
+ rv.WriteString(`.`)
+ rv.WriteString(``)
+ appendLeftSeparatedNumberSpans(rv, amount[i+1:], "ns")
+ rv.WriteString("")
+ }
+ rv.WriteString(" ")
+ rv.WriteString(shortcut)
+ rv.WriteString("")
+}
+
+func (s *PublicServer) amount(a *api.Amount, td *TemplateData, classes string) template.HTML {
+ primary := s.formatAmount(a)
+ var rv strings.Builder
+ rv.WriteString(``)
+ appendAmountSpan(&rv, "prim-amt", primary, td.CoinShortcut, "")
+ if td.SecondaryCoin != "" {
+ base, err := strconv.ParseFloat(primary, 64)
+ if err == nil {
+ currentSecondary := strconv.FormatFloat(base*td.CurrentSecondaryCoinRate, 'f', 2, 64)
+ blocktimeSecondary := ""
+ // if tx is specified, secondary amount is at the time of tx and current amount with class "csec-amt"
+ if td.Tx != nil {
+ if td.Tx.Blocktime != td.TxBlocktime {
+ td.TxBlocktime = td.Tx.Blocktime
+ date := time.Unix(td.Tx.Blocktime, 0).UTC()
+ secondary := strings.ToLower(td.SecondaryCoin)
+ ticker, _ := s.db.FiatRatesFindTicker(&date, secondary, "")
+ if ticker != nil {
+ td.TxBlocktimeSecondaryCoinRate = float64(ticker.Rates[secondary])
+ // the ticker is from the midnight, valid for the whole day before
+ td.TxDate = date.Add(-1 * time.Second).Format("2006-01-02")
+ }
+ }
+ if td.TxBlocktimeSecondaryCoinRate != 0 {
+ blocktimeSecondary = strconv.FormatFloat(base*td.TxBlocktimeSecondaryCoinRate, 'f', 2, 64)
+ }
+ }
+ if blocktimeSecondary != "" {
+ appendAmountSpan(&rv, "sec-amt", blocktimeSecondary, td.SecondaryCoin, td.TxDate)
+ appendAmountSpan(&rv, "csec-amt", currentSecondary, td.SecondaryCoin, "")
+ } else {
+ appendAmountSpan(&rv, "sec-amt", currentSecondary, td.SecondaryCoin, "")
+ }
+ }
+ }
+ rv.WriteString("")
+ return template.HTML(rv.String())
+}
+
func formatInt(i int) template.HTML {
return formatInt64(int64(i))
}
@@ -629,23 +750,58 @@ func formatUint32(i uint32) template.HTML {
return formatInt64(int64(i))
}
-func formatInt64(i int64) template.HTML {
- s := strconv.FormatInt(i, 10)
+func appendSeparatedNumberSpans(rv *strings.Builder, s, separatorClass string) {
t := (len(s) - 1) / 3
if t <= 0 {
- return template.HTML(s)
+ rv.WriteString(s)
+ } else {
+ t *= 3
+ rv.WriteString(s[:len(s)-t])
+ for i := len(s) - t; i < len(s); i += 3 {
+ rv.WriteString(``)
+ rv.WriteString(s[i : i+3])
+ rv.WriteString("")
+ }
}
- t *= 3
- rv := s[:len(s)-t]
- for i := len(s) - t; i < len(s); i += 3 {
- rv += `` + s[i:i+3] + ""
+}
+
+func appendLeftSeparatedNumberSpans(rv *strings.Builder, s, separatorClass string) {
+ l := len(s)
+ if l <= 3 {
+ rv.WriteString(s)
+ } else {
+ rv.WriteString(s[:3])
+ for i := 3; i < len(s); i += 3 {
+ rv.WriteString(``)
+ e := i + 3
+ if e > l {
+ e = l
+ }
+ rv.WriteString(s[i:e])
+ rv.WriteString("")
+ }
}
- return template.HTML(rv)
+}
+
+func formatInt64(i int64) template.HTML {
+ s := strconv.FormatInt(i, 10)
+ var rv strings.Builder
+ appendSeparatedNumberSpans(&rv, s, "ns")
+ return template.HTML(rv.String())
}
// called from template to support txdetail.html functionality
func setTxToTemplateData(td *TemplateData, tx *api.Tx) *TemplateData {
td.Tx = tx
+ // reset the TxBlocktimeSecondaryCoinRate if different Blocktime
+ if td.TxBlocktime != tx.Blocktime {
+ td.TxBlocktime = 0
+ td.TxBlocktimeSecondaryCoinRate = 0
+ }
return td
}
@@ -704,7 +860,7 @@ func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) (tpl,
return errorTpl, nil, err
}
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.Tx = tx
return txTpl, data, nil
}
@@ -814,7 +970,7 @@ func (s *PublicServer) explorerAddress(w http.ResponseWriter, r *http.Request) (
if err != nil {
return errorTpl, nil, err
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.AddrStr = address.AddrStr
data.Address = address
data.Page = address.Page
@@ -844,7 +1000,7 @@ func (s *PublicServer) explorerNftDetail(w http.ResponseWriter, r *http.Request)
if ci == nil {
return errorTpl, nil, api.NewAPIError(fmt.Sprintf("Unknown contract %s", contract), true)
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.TokenId = tokenId
data.ContractInfo = ci
data.URI = uri
@@ -870,7 +1026,7 @@ func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl
}
return errorTpl, nil, err
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.AddrStr = address.AddrStr
data.Address = address
data.Page = address.Page
@@ -895,7 +1051,7 @@ func (s *PublicServer) explorerBlocks(w http.ResponseWriter, r *http.Request) (t
if err != nil {
return errorTpl, nil, err
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.Blocks = blocks
data.Page = blocks.Page
data.PagingRange, data.PrevPage, data.NextPage = getPagingRange(blocks.Page, blocks.TotalPages)
@@ -916,7 +1072,7 @@ func (s *PublicServer) explorerBlock(w http.ResponseWriter, r *http.Request) (tp
return errorTpl, nil, err
}
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.Block = block
data.Page = block.Page
data.PagingRange, data.PrevPage, data.NextPage = getPagingRange(block.Page, block.TotalPages)
@@ -931,7 +1087,7 @@ func (s *PublicServer) explorerIndex(w http.ResponseWriter, r *http.Request) (tp
if err != nil {
return errorTpl, nil, err
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.Info = si
return indexTpl, data, nil
}
@@ -970,7 +1126,7 @@ func (s *PublicServer) explorerSearch(w http.ResponseWriter, r *http.Request) (t
func (s *PublicServer) explorerSendTx(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
s.metrics.ExplorerViews.With(common.Labels{"action": "sendtx"}).Inc()
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
if r.Method == http.MethodPost {
err := r.ParseForm()
if err != nil {
@@ -1002,7 +1158,7 @@ func (s *PublicServer) explorerMempool(w http.ResponseWriter, r *http.Request) (
if err != nil {
return errorTpl, nil, err
}
- data := s.newTemplateData()
+ data := s.newTemplateData(r)
data.MempoolTxids = mempoolTxids
data.Page = mempoolTxids.Page
data.PagingRange, data.PrevPage, data.NextPage = getPagingRange(mempoolTxids.Page, mempoolTxids.TotalPages)
diff --git a/static/css/main.css b/static/css/main.css
index 82d4ae64..065d214b 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -1,86 +1,32 @@
-html, body {
+@import "TTHoves/TTHoves.css";
+
+* {
+ margin: 0px;
+ padding: 0px;
+ outline: none;
+ font-family: "TT Hoves", -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
+}
+
+html,
+body {
height: 100%;
}
body {
- width: 100%;
min-height: 100%;
- background-color: #ffffff;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
- font-size: 11px;
+ margin: 0;
+ background: linear-gradient(to bottom, #f6f6f6 300px, #e5e5e5 0), #e5e5e5;
+ background-repeat: no-repeat;
}
a {
- color: #428bca;
+ color: #00854d;
text-decoration: none;
}
-h1 small {
- font-size: 65%;
-}
-
-h3 {
- margin-top: 20px;
-}
-
-.octicon {
- color: #777;
- display: inline-block;
- vertical-align: text-top;
- fill: currentColor;
- height: 16px;
-}
-
-.navbar-form {
- padding-bottom: 1px;
-}
-
-.navbar-form .form-control {
- background-color: gray;
- color: #fff;
- border-radius: 3px;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border: 0;
- -webkit-box-shadow: 1px 1px 0 0 rgba(255, 255, 255, .41), inset 1px 1px 3px 0 rgba(0, 0, 0, .10);
- -moz-box-shadow: 1px 1px 0 0 rgba(255, 255, 255, .41), inset 1px 1px 3px 0 rgba(0, 0, 0, .10);
- box-shadow: 1px 1px 0 0 rgba(255, 255, 255, .41), inset 1px 1px 3px 0 rgba(0, 0, 0, .10);
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 750px;
- }
-}
-
-@media (min-width: 992px) {
- body {
- font-size: 12px;
- }
- .container {
- max-width: 970px;
- }
- .octicon {
- height: 24px;
- }
- .navbar-form .form-control {
- width: 230px;
- }
-}
-
-@media (min-width: 1200px) {
- body {
- font-size: 14px;
- }
- .container {
- max-width: 1170px;
- }
- .octicon {
- height: 32px;
- }
- .navbar-form .form-control {
- width: 360px;
- }
+a:hover {
+ color: #00854d;
+ text-decoration: underline;
}
#header {
@@ -91,121 +37,136 @@ h3 {
margin: 0;
padding-bottom: 0;
padding-top: 0;
- background-color: #212121;
+ background-color: white;
border: 0;
+ z-index: 10;
}
-.bg-trezor {
- background-color: #212121!important;
- padding-top: 3px;
- padding-bottom: 2px;
- z-index: 2;
+#header .navbar {
+ --bs-navbar-padding-y: 0.7rem;
}
-.bg-trezor .navbar-brand {
- color: rgba(255, 255, 255);
+#header .form-control-lg {
+ font-size: 1rem;
+ padding: 0.75rem 1rem;
+}
+
+#header .container {
+ min-height: 50px;
+}
+
+.bb-group {
+ border: 0.6rem solid #f6f6f6;
+ background-color: #f6f6f6;
+ border-radius: 0.5rem;
+ position: relative;
+ display: inline-flex;
+ vertical-align: middle;
+}
+
+.bb-group>.btn {
+ --bs-btn-padding-x: 0.5rem;
+ --bs-btn-padding-y: 0.22rem;
+ --bs-btn-border-radius: 0.3rem;
+ --bs-btn-border-width: 0;
+ color: #545454;
+}
+
+.bb-group>.btn-check:checked+.btn,
+.bb-group .btn.active {
+ color: black;
font-weight: bold;
- font-size: 19px;
- fill: #FFFFFF;
+ background-color: white;
}
-@media (max-width: 768px) {
- .navbar {
- font-size: 14px;
- }
- .bg-trezor .navbar-brand {
- font-weight: normal;
- font-size: 14px;
- }
+.paging {
+ display: flex;
+}
+
+.paging .bb-group>.btn {
+ min-width: 2rem;
+ margin-left: 0.1rem;
+ margin-right: 0.1rem;
+}
+
+.paging .bb-group>.btn:hover {
+ background-color: white;
+}
+
+.paging a {
+ text-decoration: none;
+}
+
+.btn-paging {
+ --bs-btn-color: #757575;
+ --bs-btn-border-color: #e2e2e2;
+ --bs-btn-hover-color: black;
+ --bs-btn-hover-bg: #f6f6f6;
+ --bs-btn-hover-border-color: #e2e2e2;
+ --bs-btn-focus-shadow-rgb: 108, 117, 125;
+ --bs-btn-active-color: #fff;
+ --bs-btn-active-bg: #e2e2e2;
+ --bs-btn-active-border-color: #e2e2e2;
+ --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ --bs-gradient: none;
+ --bs-btn-padding-y: 0.75rem;
+ --bs-btn-padding-x: 1.1rem;
+ --bs-btn-border-radius: 0.5rem;
+ --bs-btn-font-weight: bold;
+ background-color: #f6f6f6;
+}
+
+span.btn-paging {
+ cursor: initial;
+}
+
+span.btn-paging:hover {
+ color: #757575;
+}
+
+.paging-group {
+ border: 1px solid #e2e2e2;
+ border-radius: 0.5rem;
+}
+
+.paging-group>.bb-group {
+ border: 0.53rem solid #f6f6f6;
}
#wrap {
min-height: 100%;
height: auto;
- padding: 75px 0;
- margin: 0 auto -42px;
+ padding: 112px 0 75px 0;
+ margin: 0 auto -56px;
}
#footer {
- background-color: #212121;
- color: #fff;
- height: 42px;
+ background-color: black;
+ color: #757575;
+ height: 56px;
overflow: hidden;
}
-.alert-data {
- color: #383d41;
- background-color: #f4f4f4;
- border-color: #d6d8db;
- padding: 15px;
+.navbar-form {
+ width: 60%;
}
-.line-top {
- border-top: 1px solid #EAEAEA;
- padding: 10px 0 0;
+.navbar-form button {
+ margin-left: -50px;
+ position: relative;
}
-.line-mid {
- padding: 15px;
+.search-icon {
+ width: 16px;
+ height: 16px;
+ position: absolute;
+ top: 16px;
+ background-size: cover;
+ background-image: url("data:image/svg+xml, %3Csvg style='background: white%3B' width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7.24976 12.5C10.1493 12.5 12.4998 10.1495 12.4998 7.25C12.4998 4.35051 10.1493 2 7.24976 2C4.35026 2 1.99976 4.35051 1.99976 7.25C1.99976 10.1495 4.35026 12.5 7.24976 12.5Z' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' /%3E%3Cpath d='M10.962 10.9625L13.9996 14.0001' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' /%3E%3C/svg%3E");
}
-.line-bot {
- border-bottom: 2px solid #EAEAEA;
- padding: 0 0 15px;
-}
-
-.txvalues {
- display: inline-block;
- padding: .7em 2em;
- font-size: 13px;
- color: #fff;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: .25em;
- margin-top: 5px;
-}
-
-.txvalues:not(:last-child) {
- margin-right: 5px;
-}
-
-.txvalues-default {
- background-color: #EBEBEB;
- color: #333;
-}
-
-.txvalues-success {
- background-color: dimgray;
-}
-
-.txvalues-primary {
- background-color: #000;
-}
-
-.txvalues-danger {
- background-color: #AC0015;
- text-transform: uppercase;
-}
-
-.tx-own {
- background-color: #fbf8f0;
-}
-
-.tx-amt {
- float: right!important;
-}
-
-.tx-in .tx-own .tx-amt {
- color: #dc3545!important;
-}
-
-.tx-out .tx-own .tx-amt {
- color: #28a745!important;
-}
-
-.tx-addr {
- float: left!important;
+.navbar-form ::placeholder {
+ color: #e2e2e2;
}
.ellipsis {
@@ -214,97 +175,359 @@ h3 {
white-space: nowrap;
}
-.data-div {
- margin: 20px 0 30px 0;
-}
-
-.data-div .col-md-10 {
- padding-left: 0;
-}
-
.data-table {
table-layout: fixed;
- border-radius: .25rem;
- background: white;
overflow-wrap: break-word;
+ margin-left: 8px;
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ width: calc(100% - 16px);
}
-.data-table td, .data-table th {
- padding: .4rem;
+.data-table thead {
+ padding-bottom: 20px;
}
-.data-table span.ellipsis {
- max-width: 100%;
+.table.data-table> :not(caption)>*>* {
+ padding: 0.8rem 0.8rem;
+ background-color: var(--bs-table-bg);
+ border-bottom-width: 1px;
+ box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg);
}
-.data {
- font-weight: bold;
+.table.data-table>thead>*>* {
+ padding-bottom: 1.5rem;
}
-table.data-table table.data-table th {
- border-top: 0;
+.table.data-table>*>*:last-child>* {
+ border-bottom: none;
+}
+
+.data-table thead,
+.data-table thead tr,
+.data-table thead th {
+ color: #757575;
+ border: none;
font-weight: normal;
}
-.alert .data-table {
- margin: 0;
+.data-table tbody {
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 0 0 8px white;
}
-::-webkit-input-placeholder {
- color: #CCC!important;
- font-style: italic;
- font-size: 14px;
-}
-
-::-moz-placeholder {
- color: #CCC!important;
- font-style: italic;
- font-size: 14px;
-}
-
-.h-container ul, .h-container h3 {
- margin: 0;
-}
-
-.h-container h5 {
- margin-top: 6px;
+.data-table h3,
+.data-table h6 {
margin-bottom: 0;
}
-.page-link {
- color: #428bca;
+.data-table h3 {
+ color: black;
}
-.page-text {
+.info-table tbody {
+ display: inline-table;
+ width: 100%;
+}
+
+.info-table td {
+ font-weight: bold;
+}
+
+.info-table tr>td:first-child {
+ font-weight: normal;
+ color: #757575;
+}
+
+.ns:before {
+ content: " ";
+}
+
+.nc:before {
+ content: ",";
+}
+
+.trezor-logo {
+ width: 128px;
+ height: 32px;
+ position: absolute;
+ top: 16px;
+ background-size: cover;
+ background-image: url("data:image/svg+xml,%3Csvg style='width: 128px%3B' version='1.1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 163.7 41.9' space='preserve'%3E%3Cpolygon points='101.1 12.8 118.2 12.8 118.2 17.3 108.9 29.9 118.2 29.9 118.2 35.2 101.1 35.2 101.1 30.7 110.4 18.1 101.1 18.1'%3E%3C/polygon%3E%3Cpath d='M158.8 26.9c2.1-0.8 4.3-2.9 4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1 7.5h6.7L158.8 26.9z M154.7 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C157.2 21.6 156.2 22.5 154.7 22.5z'%3E%3C/path%3E%3Cpath d='M130.8 12.5c-6.8 0-11.6 4.9-11.6 11.5s4.9 11.5 11.6 11.5s11.7-4.9 11.7-11.5S137.6 12.5 130.8 12.5z M130.8 30.3c-3.4 0-5.7-2.6-5.7-6.3c0-3.8 2.3-6.3 5.7-6.3c3.4 0 5.8 2.6 5.8 6.3C136.6 27.7 134.2 30.3 130.8 30.3z'%3E%3C/path%3E%3Cpolygon points='82.1 12.8 98.3 12.8 98.3 18 87.9 18 87.9 21.3 98 21.3 98 26.4 87.9 26.4 87.9 30 98.3 30 98.3 35.2 82.1 35.2'%3E%3C/polygon%3E%3Cpath d='M24.6 9.7C24.6 4.4 20 0 14.4 0S4.2 4.4 4.2 9.7v3.1H0v22.3h0l14.4 6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4 9.7c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5v3.1H9.4V9.7z M23 31.5l-8.6 4l-8.6-4V18.1H23V31.5z'%3E%3C/path%3E%3Cpath d='M79.4 20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1 7.5H80l-4.9-8.3C77.2 26.1 79.4 24 79.4 20.3z M71 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C73.5 21.6 72.5 22.5 71 22.5z'%3E%3C/path%3E%3Cpolygon points='40.5 12.8 58.6 12.8 58.6 18.1 52.4 18.1 52.4 35.2 46.6 35.2 46.6 18.1 40.5 18.1'%3E%3C/polygon%3E%3C/svg%3E");
+}
+
+.copyable::before,
+.copied::before {
+ width: 18px;
+ height: 16px;
+ margin: 3px -18px;
+ content: "";
+ position: absolute;
+ background-size: cover;
+}
+
+.copyable::before {
+ display: none;
+ cursor: copy;
+ background-image: url("data:image/svg+xml,%3Csvg width='18' height='16' viewBox='0 0 18 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 10.4996H13.5V2.49963H5.5V5.49963' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.4998 5.49976H2.49976V13.4998H10.4998V5.49976Z' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
+}
+
+.copyable:hover::before {
+ display: inline-block;
+}
+
+.copied::before {
+ transition: all 0.4s ease;
+ transform: scale(1.2);
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='16' viewBox='-30 -30 330 330'%3E%3Cpath d='M 30,180 90,240 240,30' style='stroke:%2300854D; stroke-width:32; fill:none'/%3E%3C/svg%3E");
+}
+
+.h-data {
+ letter-spacing: 0.12em;
+ font-weight: normal !important;
+}
+
+.tx-detail {
+ background: #f6f6f6;
+ color: #757575;
+ border-radius: 10px;
+ box-shadow: 0 0 0 10px white;
+ width: calc(100% - 20px);
+ margin-left: 10px;
+ margin-top: 3rem;
+ overflow-wrap: break-word;
+}
+
+.tx-detail:first-child {
+ margin-top: 1rem;
+}
+
+.tx-detail:last-child {
+ margin-bottom: 3rem;
+}
+
+.tx-detail span.ellipsis,
+.tx-detail a.ellipsis {
display: block;
- padding: .5rem .3rem;
- line-height: 1.25;
+ float: left;
+ max-width: 100%;
}
-.page-link {
- color: #428bca;
+.tx-detail>.head {
+ padding: 1.5rem;
+ border-radius: 10px 10px 0 0;
+ --bs-gutter-x: 0;
}
-.page-item.active .page-link {
- background-color: #428bca;
+.tx-detail .txid {
+ font-size: 106%;
+ letter-spacing: -0.01em;
}
-#txSpecific {
- margin: 0;
+.tx-detail>.body {
+ padding: 0 1.5rem;
+ --bs-gutter-x: 0;
+ letter-spacing: -0.01em;
}
-.string {
- color: darkgreen;
+.tx-detail>.footer {
+ padding: 1.5rem;
+ --bs-gutter-x: 0;
}
-.number, .boolean {
- color: darkred;
+.tx-in .col-12,
+.tx-out .col-12 {
+ background-color: white;
+ padding: 1.2rem 1.3rem;
+ border-bottom: 1px solid #f6f6f6;
}
-.null {
+.tx-in .col-12:last-child,
+.tx-out .co-12l:last-child {
+ border-bottom: none;
+}
+
+.tx-own {
+ background-color: #fff9e3 !important;
+}
+
+.tx-amt {
+ float: right !important;
+}
+
+.spent {
+ color: #dc3545 !important;
+}
+
+.unspent {
+ color: #28a745 !important;
+}
+
+.outpoint {
+ color: #757575 !important;
+}
+
+.spent,
+.unspent,
+.outpoint {
+ display: inline-block;
+ text-align: right;
+ min-width: 18px;
+ text-decoration: none !important;
+}
+
+.octicon {
+ height: 24px;
+ width: 24px;
+ margin-left: -12px;
+ margin-top: 19px;
+ position: absolute;
+ background-size: cover;
+ background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 4.5L16.5 12L9 19.5' stroke='%23AFAFAF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
+}
+
+.txvalue {
+ color: var(--bs-body-color);
+ font-weight: bold;
+}
+
+.tx-amt .amt:hover,
+.tx-amt.amt:hover {
+ color: var(--bs-body-color);
+}
+
+.prim-amt {
+ display: initial;
+}
+
+.sec-amt {
+ display: none;
+}
+
+.csec-amt {
+ display: none;
+}
+
+.tooltip {
+ --bs-tooltip-opacity: 1;
+ --bs-tooltip-max-width: 320px;
+ --bs-tooltip-bg: #fff;
+ --bs-tooltip-color: var(--bs-body-color);
+ --bs-tooltip-padding-x: 1rem;
+ --bs-tooltip-padding-y: 0.8rem;
+ filter: drop-shadow(0px 24px 64px rgba(22, 27, 45, 0.25));
+}
+
+.amt-tooltip {
+ text-align: start;
+ display: inline-block;
+}
+
+.amt-tooltip .prim-amt,
+.amt-tooltip .sec-amt,
+.amt-tooltip .csec-amt {
+ display: initial;
+ float: right;
+}
+
+.amt-dec {
+ font-size: 97%;
+}
+
+.amt-tooltip .amt-time {
+ padding-right: 3rem;
+ float: left;
+}
+
+.unconfirmed {
+ color: white;
+ background-color: #c51e13;
+ padding: 0.7rem 1.2rem;
+ border-radius: 1.4rem;
+}
+
+.json {
+ word-wrap: break-word;
+ font-size: smaller;
+ background: #002b31;
+ border-radius: 8px;
+}
+
+#raw {
+ padding: 1.5rem 2rem;
+ color: #ffffff;
+ letter-spacing: 0.02em;
+}
+
+#raw .string {
+ color: #2bca87;
+}
+
+#raw .number,
+#raw .boolean {
+ color: #efc941;
+}
+
+#raw .null {
color: red;
}
-.key {
- color: #333;
+@media (max-width: 768px) {
+ body {
+ font-size: 0.8rem;
+ }
+
+ .octicon {
+ scale: 60% !important;
+ margin-top: -2px;
+ }
+
+ .btn {
+ --bs-btn-font-size: 0.8rem;
+ }
+}
+
+@media (max-width: 991px) {
+ #header .container {
+ min-height: 40px;
+ }
+
+ .trezor-logo {
+ top: 10px;
+ }
+
+ .octicon {
+ scale: 80%;
+ }
+
+ .table.data-table>:not(caption)>*>* {
+ padding: 0.8rem 0.4rem;
+ }
+}
+
+@media (min-width: 769px) {
+ body {
+ font-size: 0.9rem;
+ }
+
+ .btn {
+ --bs-btn-font-size: 0.9rem;
+ }
+}
+
+@media (min-width: 1200px) {
+
+ .h1,
+ h1 {
+ font-size: 2.4rem;
+ }
+
+ body {
+ font-size: 1rem;
+ }
+
+ .btn {
+ --bs-btn-font-size: 1rem;
+ }
}
\ No newline at end of file
diff --git a/static/css/main2.css b/static/css/main2.css
deleted file mode 100644
index 0ea1a4fb..00000000
--- a/static/css/main2.css
+++ /dev/null
@@ -1,483 +0,0 @@
-@import "TTHoves/TTHoves.css";
-
-* {
- margin: 0px;
- padding: 0px;
- outline: none;
- font-family: "TT Hoves", -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
-}
-
-html,
-body {
- height: 100%;
-}
-
-body {
- min-height: 100%;
- margin: 0;
- background: linear-gradient(to bottom, #F6F6F6 300px, #E5E5E5 0), #E5E5E5;
- background-repeat: no-repeat;
-}
-
-a {
- color: #00854D;
- text-decoration: none;
-}
-
-a:hover {
- color: #00854D;
- text-decoration: underline;
-}
-
-#header {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- margin: 0;
- padding-bottom: 0;
- padding-top: 0;
- background-color: white;
- border: 0;
- z-index: 10;
-}
-
-#header .navbar {
- --bs-navbar-padding-y: 0.7rem;
-}
-
-#header .form-control-lg {
- font-size: 1rem;
- padding: 0.75rem 1rem;
-}
-
-#header .container {
- min-height: 50px;
-}
-
-.bb-group {
- border: 0.6rem solid #F6F6F6;
- background-color: #F6F6F6;
- border-radius: 0.5rem;
- position: relative;
- display: inline-flex;
- vertical-align: middle;
-}
-
-.bb-group>.btn {
- --bs-btn-padding-x: 0.5rem;
- --bs-btn-padding-y: 0.22rem;
- --bs-btn-border-radius: 0.3rem;
- --bs-btn-border-width: 0;
- color: #545454;
-}
-
-.bb-group>.btn-check:checked+.btn,
-.bb-group .btn.active {
- color: black;
- font-weight: bold;
- background-color: white;
-}
-
-.paging {
- display: flex;
-}
-
-.paging .bb-group>.btn {
- min-width: 2rem;
- margin-left: 0.1rem;
- margin-right: 0.1rem;
-}
-
-.paging .bb-group>.btn:hover {
- background-color: white;
-}
-
-.paging a {
- text-decoration: none;
-}
-
-.btn-paging {
- --bs-btn-color: #757575;
- --bs-btn-border-color: #E2E2E2;
- --bs-btn-hover-color: black;
- --bs-btn-hover-bg: #F6F6F6;
- --bs-btn-hover-border-color: #E2E2E2;
- --bs-btn-focus-shadow-rgb: 108, 117, 125;
- --bs-btn-active-color: #fff;
- --bs-btn-active-bg: #E2E2E2;
- --bs-btn-active-border-color: #E2E2E2;
- --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- --bs-gradient: none;
- --bs-btn-padding-y: 0.75rem;
- --bs-btn-padding-x: 1.1rem;
- --bs-btn-border-radius: 0.5rem;
- --bs-btn-font-weight: bold;
- background-color: #F6F6F6;
-}
-
-span.btn-paging {
- cursor: initial;
-}
-
-span.btn-paging:hover {
- color: #757575;
-}
-
-.paging-group {
- border: 1px solid #E2E2E2;
- border-radius: 0.5rem;
-}
-
-.paging-group>.bb-group {
- border: 0.53rem solid #F6F6F6;
-}
-
-#wrap {
- min-height: 100%;
- height: auto;
- padding: 112px 0 75px 0;
- margin: 0 auto -56px;
-}
-
-#footer {
- background-color: black;
- color: #757575;
- height: 56px;
- overflow: hidden;
-}
-
-.navbar-form {
- width: 60%;
-}
-
-.navbar-form button {
- margin-left: -50px;
- position: relative;
-}
-
-.search-icon {
- width: 16px;
- height: 16px;
- position: absolute;
- top: 16px;
- background-size: cover;
- background-image: url("data:image/svg+xml, %3Csvg style='background: white%3B' width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7.24976 12.5C10.1493 12.5 12.4998 10.1495 12.4998 7.25C12.4998 4.35051 10.1493 2 7.24976 2C4.35026 2 1.99976 4.35051 1.99976 7.25C1.99976 10.1495 4.35026 12.5 7.24976 12.5Z' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' /%3E%3Cpath d='M10.962 10.9625L13.9996 14.0001' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' /%3E%3C/svg%3E");
-}
-
-.navbar-form ::placeholder {
- color: #E2E2E2;
-}
-
-.ellipsis {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.data-table {
- table-layout: fixed;
- overflow-wrap: break-word;
- margin-left: 8px;
- margin-top: 2rem;
- margin-bottom: 2rem;
- width: calc(100% - 16px);
-}
-
-.data-table thead {
- padding-bottom: 20px;
-}
-
-.table.data-table>:not(caption)>*>* {
- padding: 0.8rem 0.8rem;
- background-color: var(--bs-table-bg);
- border-bottom-width: 1px;
- box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg);
-}
-
-.table.data-table>thead>*>* {
- padding-bottom: 1.5rem;
-}
-
-.table.data-table>*>*:last-child>* {
- border-bottom: none;
-}
-
-.data-table thead,
-.data-table thead tr,
-.data-table thead th {
- color: #757575;
- border: none;
- font-weight: normal;
-}
-
-.data-table tbody {
- background: white;
- border-radius: 8px;
- box-shadow: 0 0 0 8px white;
-}
-
-.data-table h3,
-.data-table h6 {
- margin-bottom: 0;
-}
-
-.data-table h3 {
- color: black;
-}
-
-.info-table tbody {
- display: inline-table;
- width: 100%;
-}
-
-.info-table td {
- font-weight: bold;
-}
-
-.info-table tr>td:first-child {
- font-weight: normal;
- color: #757575;
-}
-
-.ns:before {
- content: " ";
-}
-
-.trezor-logo {
- width: 128px;
- height: 32px;
- position: absolute;
- top: 16px;
- background-size: cover;
- background-image: url("data:image/svg+xml,%3Csvg style='width: 128px%3B' version='1.1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 163.7 41.9' space='preserve'%3E%3Cpolygon points='101.1 12.8 118.2 12.8 118.2 17.3 108.9 29.9 118.2 29.9 118.2 35.2 101.1 35.2 101.1 30.7 110.4 18.1 101.1 18.1'%3E%3C/polygon%3E%3Cpath d='M158.8 26.9c2.1-0.8 4.3-2.9 4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1 7.5h6.7L158.8 26.9z M154.7 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C157.2 21.6 156.2 22.5 154.7 22.5z'%3E%3C/path%3E%3Cpath d='M130.8 12.5c-6.8 0-11.6 4.9-11.6 11.5s4.9 11.5 11.6 11.5s11.7-4.9 11.7-11.5S137.6 12.5 130.8 12.5z M130.8 30.3c-3.4 0-5.7-2.6-5.7-6.3c0-3.8 2.3-6.3 5.7-6.3c3.4 0 5.8 2.6 5.8 6.3C136.6 27.7 134.2 30.3 130.8 30.3z'%3E%3C/path%3E%3Cpolygon points='82.1 12.8 98.3 12.8 98.3 18 87.9 18 87.9 21.3 98 21.3 98 26.4 87.9 26.4 87.9 30 98.3 30 98.3 35.2 82.1 35.2'%3E%3C/polygon%3E%3Cpath d='M24.6 9.7C24.6 4.4 20 0 14.4 0S4.2 4.4 4.2 9.7v3.1H0v22.3h0l14.4 6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4 9.7c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5v3.1H9.4V9.7z M23 31.5l-8.6 4l-8.6-4V18.1H23V31.5z'%3E%3C/path%3E%3Cpath d='M79.4 20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1 7.5H80l-4.9-8.3C77.2 26.1 79.4 24 79.4 20.3z M71 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C73.5 21.6 72.5 22.5 71 22.5z'%3E%3C/path%3E%3Cpolygon points='40.5 12.8 58.6 12.8 58.6 18.1 52.4 18.1 52.4 35.2 46.6 35.2 46.6 18.1 40.5 18.1'%3E%3C/polygon%3E%3C/svg%3E");
-}
-
-.copyable::before,
-.copied::before {
- width: 18px;
- height: 16px;
- margin: 3px -18px;
- content: "";
- position: absolute;
- background-size: cover;
-}
-
-.copyable::before {
- display: none;
- cursor: pointer;
- background-image: url("data:image/svg+xml,%3Csvg width='18' height='16' viewBox='0 0 18 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 10.4996H13.5V2.49963H5.5V5.49963' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.4998 5.49976H2.49976V13.4998H10.4998V5.49976Z' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
-}
-
-.copyable:hover::before {
- display: inline-block;
-}
-
-.copied::before {
- transition: all 0.4s ease;
- transform: scale(1.2);
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='16' viewBox='-30 -30 330 330'%3E%3Cpath d='M 30,180 90,240 240,30' style='stroke:%2300854D; stroke-width:32; fill:none'/%3E%3C/svg%3E");
-}
-
-.h-data {
- letter-spacing: 0.12em;
- font-weight: normal !important;
-}
-
-.tx-detail {
- background: #F6F6F6;
- color: #757575;
- border-radius: 10px;
- box-shadow: 0 0 0 10px white;
- width: calc(100% - 20px);
- margin-left: 10px;
- margin-top: 3rem;
- overflow-wrap: break-word;
-}
-
-.tx-detail:first-child {
- margin-top: 1rem;
-}
-
-.tx-detail:last-child {
- margin-bottom: 3rem;
-}
-
-.tx-detail span.ellipsis,
-.tx-detail a.ellipsis {
- display: block;
- float: left;
- max-width: 100%;
-}
-
-.tx-detail>.head {
- padding: 1.5rem;
- border-radius: 10px 10px 0 0;
- --bs-gutter-x: 0;
-}
-
-.tx-detail .txid {
- font-size: 106%;
- letter-spacing: -0.01em;
-}
-
-.tx-detail>.body {
- padding: 0 1.5rem;
- --bs-gutter-x: 0;
- letter-spacing: -0.01em;
-}
-
-.tx-detail>.footer {
- padding: 1.5rem;
- --bs-gutter-x: 0;
-}
-
-.tx-in .col-12,
-.tx-out .col-12 {
- background-color: white;
- padding: 1.2rem 1.3rem;
- border-bottom: 1px solid #F6F6F6;
-}
-
-.tx-in .col-12:last-child,
-.tx-out .co-12l:last-child {
- border-bottom: none;
-}
-
-.tx-own {
- background-color: #FFF9E3 !important;
-}
-
-.tx-amt {
- float: right !important;
-}
-
-.tx-in .tx-own .tx-amt,
-.spent {
- color: #dc3545 !important;
-}
-
-.tx-out .tx-own .tx-amt,
-.unspent {
- color: #28a745 !important;
-}
-
-.outpoint {
- color: #757575 !important;
-}
-
-.spent,
-.unspent,
-.outpoint {
- display: inline-block;
- text-align: right;
- min-width: 18px;
- text-decoration: none !important;
-}
-
-.octicon {
- height: 24px;
- width: 24px;
- margin-left: -12px;
- margin-top: 19px;
- position: absolute;
- background-size: cover;
- background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 4.5L16.5 12L9 19.5' stroke='%23AFAFAF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
-}
-
-.txvalue {
- color: black;
- font-weight: bold;
-}
-
-.unconfirmed {
- color: white;
- background-color: #C51E13;
- padding: 0.7rem 1.2rem;
- border-radius: 1.4rem;
-}
-
-.json {
- word-wrap: break-word;
- font-size: smaller;
- background: #002B31;
- border-radius: 8px;
-}
-
-#raw {
- padding: 1.5rem 2rem;
- color: #FFFFFF;
- letter-spacing: 0.02em;
-}
-
-#raw .string {
- color: #2BCA87;
-}
-
-#raw .number,
-#raw .boolean {
- color: #EFC941;
-}
-
-#raw .null {
- color: red;
-}
-
-@media (max-width: 768px) {
- body {
- font-size: 0.8rem;
- }
-
- .octicon {
- scale: 60% !important;
- margin-top: -2px;
- }
-
- .btn {
- --bs-btn-font-size: 0.8rem;
- }
-}
-
-@media (max-width: 991px) {
- #header .container {
- min-height: 40px
- }
-
- .trezor-logo {
- top: 10px;
- }
-
- .octicon {
- scale: 80%;
- }
-
- .table.data-table>:not(caption)>*>* {
- padding: 0.8rem 0.4rem;
- }
-}
-
-@media (min-width: 769px) {
- body {
- font-size: 0.9rem;
- }
-
- .btn {
- --bs-btn-font-size: 0.9rem;
- }
-}
-
-@media (min-width: 1200px) {
-
- .h1,
- h1 {
- font-size: 2.4rem;
- }
-
- body {
- font-size: 1rem;
- }
-
- .btn {
- --bs-btn-font-size: 1rem;
- }
-}
\ No newline at end of file
diff --git a/static/js/main.js b/static/js/main.js
new file mode 100644
index 00000000..77755139
--- /dev/null
+++ b/static/js/main.js
@@ -0,0 +1,116 @@
+function syntaxHighlight(json) {
+ json = JSON.stringify(json, undefined, 2);
+ json = json
+ .replace(/&/g, "&")
+ .replace(//g, ">");
+ return json.replace(
+ /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
+ (match) => {
+ let cls = "number";
+ if (/^"/.test(match)) {
+ if (/:$/.test(match)) {
+ cls = "key";
+ } else {
+ cls = "string";
+ }
+ } else if (/true|false/.test(match)) {
+ cls = "boolean";
+ } else if (/null/.test(match)) {
+ cls = "null";
+ }
+ return `${match}`;
+ }
+ );
+}
+
+function getCoinCookie() {
+ return document.cookie
+ .split("; ")
+ .find((row) => row.startsWith("secondary_coin="))
+ ?.split("=");
+}
+
+function changeCSSStyle(selector, cssProp, cssVal) {
+ const mIndex = 1;
+ const cssRules = document.all ? "rules" : "cssRules";
+ for (
+ i = 0, len = document.styleSheets[mIndex][cssRules].length;
+ i < len;
+ i++
+ ) {
+ if (document.styleSheets[mIndex][cssRules][i].selectorText === selector) {
+ document.styleSheets[mIndex][cssRules][i].style[cssProp] = cssVal;
+ return;
+ }
+ }
+}
+
+function amountTooltip() {
+ const prim = this.querySelector(".prim-amt");
+ const sec = this.querySelector(".sec-amt");
+ const csec = this.querySelector(".csec-amt");
+ let s = `${prim.outerHTML}
`;
+ if (sec) {
+ let t = sec.getAttribute("tm");
+ if (!t) {
+ t = "now";
+ }
+ s += `${t}${sec.outerHTML}
`;
+ }
+ if (csec) {
+ s += `now${csec.outerHTML}`;
+ }
+ return `${s}`;
+}
+
+window.addEventListener("DOMContentLoaded", () => {
+ const a = getCoinCookie();
+ if (a?.length === 3) {
+ if (a[2] === "true") {
+ changeCSSStyle(".prim-amt", "display", "none");
+ changeCSSStyle(".sec-amt", "display", "initial");
+ }
+ document
+ .querySelectorAll(".amt")
+ .forEach(
+ (e) => new bootstrap.Tooltip(e, { title: amountTooltip, html: true })
+ );
+ }
+
+ document
+ .querySelectorAll("[tt]")
+ .forEach((e) => new bootstrap.Tooltip(e, { title: e.getAttribute("tt") }));
+
+ document.querySelectorAll("#header .bb-group>.btn-check").forEach((e) =>
+ e.addEventListener("click", (e) => {
+ const a = getCoinCookie();
+ const sc = e.target.id === "secondary-coin";
+ if (a?.length === 3 && (a[2] === "true") !== sc) {
+ document.cookie = `${a[0]}=${a[1]}=${sc}; Path=/`;
+ changeCSSStyle(".prim-amt", "display", sc ? "none" : "initial");
+ changeCSSStyle(".sec-amt", "display", sc ? "initial" : "none");
+ }
+ })
+ );
+
+ document.querySelectorAll(".copyable").forEach((e) =>
+ e.addEventListener("click", (e) => {
+ if (e.clientX < e.target.getBoundingClientRect().x) {
+ let t = e.target.getAttribute("cc");
+ if (!t) t = e.target.innerText;
+ navigator.clipboard.writeText(t);
+ e.target.className = e.target.className.replace("copyable", "copied");
+ setTimeout(
+ () =>
+ (e.target.className = e.target.className.replace(
+ "copied",
+ "copyable"
+ )),
+ 1000
+ );
+ e.preventDefault();
+ }
+ })
+ );
+});
diff --git a/static/templates/base.html b/static/templates/base.html
index e54a7fb6..4793091d 100644
--- a/static/templates/base.html
+++ b/static/templates/base.html
@@ -5,47 +5,12 @@
-
+
+