From 9c142663ce5e5ce5f91cf0c6695e10d03efbe285 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Thu, 13 Dec 2018 00:41:58 +0100 Subject: [PATCH] Add type api.Amount for proper formatting of amounts in json --- api/types.go | 114 +++++++++++--------- api/types_test.go | 51 +++++++++ api/worker.go | 109 +++++++++---------- bchain/coins/eth/ethparser.go | 14 ++- server/public.go | 24 +++-- server/socketio.go | 14 +-- server/websocket.go | 2 +- static/templates/address.html | 14 +-- static/templates/tx.html | 10 +- static/templates/txdetail.html | 10 +- static/templates/txdetail_ethereumtype.html | 10 +- 11 files changed, 216 insertions(+), 156 deletions(-) create mode 100644 api/types_test.go diff --git a/api/types.go b/api/types.go index 644fc87e..35c368a2 100644 --- a/api/types.go +++ b/api/types.go @@ -2,7 +2,6 @@ package api import ( "blockbook/bchain" - "blockbook/bchain/coins/eth" "blockbook/common" "blockbook/db" "encoding/json" @@ -42,6 +41,17 @@ func NewAPIError(s string, public bool) error { } } +// Amount is datatype holding amounts +type Amount big.Int + +// MarshalJSON Amount serialization +func (a *Amount) MarshalJSON() (out []byte, err error) { + if a == nil { + return []byte(`"0"`), nil + } + return []byte(`"` + (*big.Int)(a).String() + `"`), nil +} + // ScriptSig contains input script type ScriptSig struct { Hex string `json:"hex"` @@ -58,8 +68,7 @@ type Vin struct { AddrDesc bchain.AddressDescriptor `json:"-"` Addresses []string `json:"addresses"` Searchable bool `json:"-"` - Value string `json:"value"` - ValueSat big.Int `json:"-"` + ValueSat *Amount `json:"value,omitempty"` } // ScriptPubKey contains output script and addresses derived from it @@ -74,8 +83,7 @@ type ScriptPubKey struct { // Vout contains information about single transaction output type Vout struct { - Value string `json:"value"` - ValueSat big.Int `json:"-"` + ValueSat *Amount `json:"value,omitempty"` N int `json:"n"` ScriptPubKey ScriptPubKey `json:"scriptPubKey"` Spent bool `json:"spent"` @@ -86,50 +94,57 @@ type Vout struct { // Erc20Token contains info about ERC20 token held by an address type Erc20Token struct { - Contract string `json:"contract"` - Txs int `json:"txs"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Decimals int `json:"decimals"` - Balance string `json:"balance,omitempty"` - BalanceSat string `json:"balanceSat,omitempty"` - ContractIndex string `json:"-"` + Contract string `json:"contract"` + Txs int `json:"txs"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals int `json:"decimals"` + BalanceSat *Amount `json:"balance,omitempty"` + ContractIndex string `json:"-"` } // Erc20Transfer contains info about ERC20 transfer done in a transaction type Erc20Transfer struct { - From string `json:"from"` - To string `json:"to"` - Contract string `json:"contract"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Tokens string `json:"tokens"` + From string `json:"from"` + To string `json:"to"` + Contract string `json:"contract"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals int `json:"decimals"` + Tokens *Amount `json:"tokens"` +} + +// EthereumSpecific contains ethereum specific transaction data +type EthereumSpecific struct { + Status int `json:"status"` // 1 OK, 0 Fail, -1 pending + Nonce uint64 `json:"nonce"` + GasLimit *big.Int `json:"gaslimit"` + GasUsed *big.Int `json:"gasused"` + GasPrice *Amount `json:"gasprice"` } // Tx holds information about a transaction type Tx struct { - Txid string `json:"txid"` - Version int32 `json:"version,omitempty"` - Locktime uint32 `json:"locktime,omitempty"` - Vin []Vin `json:"vin"` - Vout []Vout `json:"vout"` - Blockhash string `json:"blockhash,omitempty"` - Blockheight int `json:"blockheight"` - Confirmations uint32 `json:"confirmations"` - Time int64 `json:"time,omitempty"` - Blocktime int64 `json:"blocktime"` - ValueOut string `json:"valueOut"` - ValueOutSat big.Int `json:"-"` - Size int `json:"size,omitempty"` - ValueIn string `json:"valueIn"` - ValueInSat big.Int `json:"-"` - Fees string `json:"fees"` - FeesSat big.Int `json:"-"` - Hex string `json:"hex,omitempty"` - CoinSpecificData interface{} `json:"-"` - CoinSpecificJSON json.RawMessage `json:"-"` - Erc20Transfers []Erc20Transfer `json:"erc20transfers,omitempty"` - EthereumSpecific *eth.EthereumTxData `json:"ethereumspecific,omitempty"` + Txid string `json:"txid"` + Version int32 `json:"version,omitempty"` + Locktime uint32 `json:"locktime,omitempty"` + Vin []Vin `json:"vin"` + Vout []Vout `json:"vout"` + Blockhash string `json:"blockhash,omitempty"` + Blockheight int `json:"blockheight"` + Confirmations uint32 `json:"confirmations"` + Time int64 `json:"time,omitempty"` + Blocktime int64 `json:"blocktime"` + ValueOut string `json:"valueOut"` + ValueOutSat *Amount `json:"-"` + Size int `json:"size,omitempty"` + ValueInSat *Amount `json:"valueIn,omitempty"` + FeesSat *Amount `json:"fees,omitempty"` + Hex string `json:"hex,omitempty"` + CoinSpecificData interface{} `json:"-"` + CoinSpecificJSON json.RawMessage `json:"-"` + Erc20Transfers []Erc20Transfer `json:"erc20transfers,omitempty"` + EthereumSpecific *EthereumSpecific `json:"ethereumspecific,omitempty"` } // Paging contains information about paging for address, blocks and block @@ -152,16 +167,14 @@ const AddressFilterOutputs = -3 type Address struct { Paging AddrStr string `json:"addrStr"` - Balance string `json:"balance"` - BalanceSat string `json:"balanceSat"` - TotalReceived string `json:"totalReceived,omitempty"` - TotalSent string `json:"totalSent,omitempty"` - UnconfirmedBalance string `json:"unconfirmedBalance"` - UnconfirmedBalanceSat string `json:"unconfirmedBalanceSat"` + BalanceSat *Amount `json:"balance"` + TotalReceivedSat *Amount `json:"totalReceived,omitempty"` + TotalSentSat *Amount `json:"totalSent,omitempty"` + UnconfirmedBalanceSat *Amount `json:"unconfirmedBalance"` UnconfirmedTxApperances int `json:"unconfirmedTxApperances"` TxApperances int `json:"txApperances"` - Transactions []*Tx `json:"txs,omitempty"` - Txids []string `json:"transactions,omitempty"` + Transactions []*Tx `json:"transactions,omitempty"` + Txids []string `json:"txids,omitempty"` Nonce string `json:"nonce,omitempty"` Erc20Contract *bchain.Erc20Contract `json:"erc20contract,omitempty"` Erc20Tokens []Erc20Token `json:"erc20tokens,omitempty"` @@ -172,8 +185,7 @@ type Address struct { type AddressUtxo struct { Txid string `json:"txid"` Vout int32 `json:"vout"` - Amount string `json:"amount"` - AmountSat big.Int `json:"satoshis"` + AmountSat *Amount `json:"value"` Height int `json:"height,omitempty"` Confirmations int `json:"confirmations"` } diff --git a/api/types_test.go b/api/types_test.go new file mode 100644 index 00000000..37026685 --- /dev/null +++ b/api/types_test.go @@ -0,0 +1,51 @@ +// build unittest + +package api + +import ( + "encoding/json" + "math/big" + "reflect" + "testing" +) + +func TestAmount_MarshalJSON(t *testing.T) { + type amounts struct { + A1 Amount `json:"a1"` + A2 Amount `json:"a2,omitempty"` + PA1 *Amount `json:"pa1"` + PA2 *Amount `json:"pa2,omitempty"` + } + tests := []struct { + name string + a amounts + want string + }{ + { + name: "empty", + want: `{"a1":"0","a2":"0","pa1":null}`, + }, + { + name: "1", + a: amounts{ + A1: (Amount)(*big.NewInt(123456)), + A2: (Amount)(*big.NewInt(787901)), + PA1: (*Amount)(big.NewInt(234567)), + PA2: (*Amount)(big.NewInt(890123)), + }, + want: `{"a1":"123456","a2":"787901","pa1":"234567","pa2":"890123"}`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, err := json.Marshal(&tt.a) + if err != nil { + t.Errorf("json.Marshal() error = %v", err) + return + } + if !reflect.DeepEqual(string(b), tt.want) { + t.Errorf("json.Marshal() = %v, want %v", string(b), tt.want) + } + }) + } +} diff --git a/api/worker.go b/api/worker.go index b3f5ef81..f453593b 100644 --- a/api/worker.go +++ b/api/worker.go @@ -59,7 +59,7 @@ func (w *Worker) setSpendingTxToVout(vout *Vout, txid string, height uint32) err } else if tsp == nil { glog.Warning("DB inconsistency: tx ", t, ": not found in txAddresses") } else if len(tsp.Inputs) > int(index) { - if tsp.Inputs[index].ValueSat.Cmp(&vout.ValueSat) == 0 { + if tsp.Inputs[index].ValueSat.Cmp((*big.Int)(vout.ValueSat)) == 0 { spentTx, spentHeight, err := w.txCache.GetTransaction(t) if err != nil { glog.Warning("Tx ", t, ": not found") @@ -113,7 +113,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, var err error var ta *db.TxAddresses var erc20t []Erc20Transfer - var ethSpecific *eth.EthereumTxData + var ethSpecific *EthereumSpecific var blockhash string if bchainTx.Confirmations > 0 { if w.chainType == bchain.ChainBitcoinType { @@ -157,7 +157,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, } if len(otx.Vout) > int(vin.Vout) { vout := &otx.Vout[vin.Vout] - vin.ValueSat = vout.ValueSat + vin.ValueSat = (*Amount)(&vout.ValueSat) vin.AddrDesc, vin.Addresses, vin.Searchable, err = w.getAddressesFromVout(vout) if err != nil { glog.Errorf("getAddressesFromVout error %v, vout %+v", err, vout) @@ -166,8 +166,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, } else { if len(tas.Outputs) > int(vin.Vout) { output := &tas.Outputs[vin.Vout] - vin.ValueSat = output.ValueSat - vin.Value = w.chainParser.AmountToDecimalString(&vin.ValueSat) + vin.ValueSat = (*Amount)(&output.ValueSat) vin.AddrDesc = output.AddrDesc vin.Addresses, vin.Searchable, err = output.Addresses(w.chainParser) if err != nil { @@ -175,8 +174,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, } } } - vin.Value = w.chainParser.AmountToDecimalString(&vin.ValueSat) - valInSat.Add(&valInSat, &vin.ValueSat) + valInSat.Add(&valInSat, (*big.Int)(vin.ValueSat)) } } else if w.chainType == bchain.ChainEthereumType { if len(bchainVin.Addresses) > 0 { @@ -194,8 +192,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, bchainVout := &bchainTx.Vout[i] vout := &vouts[i] vout.N = i - vout.ValueSat = bchainVout.ValueSat - vout.Value = w.chainParser.AmountToDecimalString(&bchainVout.ValueSat) + vout.ValueSat = (*Amount)(&bchainVout.ValueSat) valOutSat.Add(&valOutSat, &bchainVout.ValueSat) vout.ScriptPubKey.Hex = bchainVout.ScriptPubKey.Hex vout.ScriptPubKey.AddrDesc, vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = w.getAddressesFromVout(bchainVout) @@ -242,20 +239,28 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, Contract: e.Contract, From: e.From, To: e.To, - Tokens: bchain.AmountToDecimalString(&e.Tokens, erc20c.Decimals), + Decimals: erc20c.Decimals, + Tokens: (*Amount)(&e.Tokens), Name: erc20c.Name, Symbol: erc20c.Symbol, } } - ethSpecific = eth.GetEthereumTxData(bchainTx) + ethTxData := eth.GetEthereumTxData(bchainTx) // mempool txs do not have fees yet - if ethSpecific.GasUsed != nil { - feesSat.Mul(ethSpecific.GasPriceNum, ethSpecific.GasUsed) + if ethTxData.GasUsed != nil { + feesSat.Mul(ethTxData.GasPrice, ethTxData.GasUsed) } if len(bchainTx.Vout) > 0 { valInSat = bchainTx.Vout[0].ValueSat } valOutSat = valInSat + ethSpecific = &EthereumSpecific{ + GasLimit: ethTxData.GasLimit, + GasPrice: (*Amount)(ethTxData.GasPrice), + GasUsed: ethTxData.GasUsed, + Nonce: ethTxData.Nonce, + Status: ethTxData.Status, + } } // for now do not return size, we would have to compute vsize of segwit transactions // size:=len(bchainTx.Hex) / 2 @@ -271,15 +276,12 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, Blockheight: int(height), Blocktime: bchainTx.Blocktime, Confirmations: bchainTx.Confirmations, - Fees: w.chainParser.AmountToDecimalString(&feesSat), - FeesSat: feesSat, + FeesSat: (*Amount)(&feesSat), Locktime: bchainTx.LockTime, Time: bchainTx.Time, Txid: bchainTx.Txid, - ValueIn: w.chainParser.AmountToDecimalString(&valInSat), - ValueInSat: valInSat, - ValueOut: w.chainParser.AmountToDecimalString(&valOutSat), - ValueOutSat: valOutSat, + ValueInSat: (*Amount)(&valInSat), + ValueOutSat: (*Amount)(&valOutSat), Version: bchainTx.Version, Hex: bchainTx.Hex, Vin: vins, @@ -331,7 +333,7 @@ func (t *Tx) getAddrVoutValue(addrDesc bchain.AddressDescriptor) *big.Int { var val big.Int for _, vout := range t.Vout { if bytes.Equal(vout.ScriptPubKey.AddrDesc, addrDesc) { - val.Add(&val, &vout.ValueSat) + val.Add(&val, (*big.Int)(vout.ValueSat)) } } return &val @@ -341,7 +343,7 @@ func (t *Tx) getAddrVinValue(addrDesc bchain.AddressDescriptor) *big.Int { var val big.Int for _, vin := range t.Vin { if bytes.Equal(vin.AddrDesc, addrDesc) { - val.Add(&val, &vin.ValueSat) + val.Add(&val, (*big.Int)(vin.ValueSat)) } } return &val @@ -371,9 +373,8 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn tai := &ta.Inputs[i] vin := &vins[i] vin.N = i - vin.ValueSat = tai.ValueSat - vin.Value = w.chainParser.AmountToDecimalString(&vin.ValueSat) - valInSat.Add(&valInSat, &vin.ValueSat) + vin.ValueSat = (*Amount)(&tai.ValueSat) + valInSat.Add(&valInSat, &tai.ValueSat) vin.Addresses, vin.Searchable, err = tai.Addresses(w.chainParser) if err != nil { glog.Errorf("tai.Addresses error %v, tx %v, input %v, tai %+v", err, txid, i, tai) @@ -384,9 +385,8 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn tao := &ta.Outputs[i] vout := &vouts[i] vout.N = i - vout.ValueSat = tao.ValueSat - vout.Value = w.chainParser.AmountToDecimalString(&vout.ValueSat) - valOutSat.Add(&valOutSat, &vout.ValueSat) + vout.ValueSat = (*Amount)(&tao.ValueSat) + valOutSat.Add(&valOutSat, &tao.ValueSat) vout.ScriptPubKey.Addresses, vout.ScriptPubKey.Searchable, err = tao.Addresses(w.chainParser) if err != nil { glog.Errorf("tai.Addresses error %v, tx %v, output %v, tao %+v", err, txid, i, tao) @@ -403,11 +403,11 @@ func (w *Worker) txFromTxAddress(txid string, ta *db.TxAddresses, bi *db.BlockIn Blockheight: int(ta.Height), Blocktime: bi.Time, Confirmations: bestheight - ta.Height + 1, - Fees: w.chainParser.AmountToDecimalString(&feesSat), + FeesSat: (*Amount)(&feesSat), Time: bi.Time, Txid: txid, - ValueIn: w.chainParser.AmountToDecimalString(&valInSat), - ValueOut: w.chainParser.AmountToDecimalString(&valOutSat), + ValueInSat: (*Amount)(&valInSat), + ValueOutSat: (*Amount)(&valOutSat), Vin: vins, Vout: vouts, } @@ -486,14 +486,8 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto } else { b = nil } - var balance, balanceSat string - if b != nil { - balance = bchain.AmountToDecimalString(b, ci.Decimals) - balanceSat = b.String() - } erc20t[i] = Erc20Token{ - Balance: balance, - BalanceSat: balanceSat, + BalanceSat: (*Amount)(b), Contract: ci.Contract, Name: ci.Name, Symbol: ci.Symbol, @@ -522,15 +516,16 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA return nil, NewAPIError(fmt.Sprintf("Invalid address, %v", err), true) } var ( - ba *db.AddrBalance - erc20t []Erc20Token - erc20c *bchain.Erc20Contract - txm []string - txs []*Tx - txids []string - pg Paging - uBalSat big.Int - totalReceived, totalSent, nonce string + ba *db.AddrBalance + erc20t []Erc20Token + erc20c *bchain.Erc20Contract + txm []string + txs []*Tx + txids []string + pg Paging + uBalSat big.Int + totalReceived, totalSent *big.Int + nonce string ) if w.chainType == bchain.ChainEthereumType { var n uint64 @@ -646,19 +641,17 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA } } if w.chainType == bchain.ChainBitcoinType { - totalReceived = w.chainParser.AmountToDecimalString(ba.ReceivedSat()) - totalSent = w.chainParser.AmountToDecimalString(&ba.SentSat) + totalReceived = ba.ReceivedSat() + totalSent = &ba.SentSat } r := &Address{ Paging: pg, AddrStr: address, - Balance: w.chainParser.AmountToDecimalString(&ba.BalanceSat), - BalanceSat: ba.BalanceSat.String(), - TotalReceived: totalReceived, - TotalSent: totalSent, + BalanceSat: (*Amount)(&ba.BalanceSat), + TotalReceivedSat: (*Amount)(totalReceived), + TotalSentSat: (*Amount)(totalSent), TxApperances: int(ba.Txs), - UnconfirmedBalance: w.chainParser.AmountToDecimalString(&uBalSat), - UnconfirmedBalanceSat: uBalSat.String(), + UnconfirmedBalanceSat: (*Amount)(&uBalSat), UnconfirmedTxApperances: len(txm), Transactions: txs, Txids: txids, @@ -714,8 +707,7 @@ func (w *Worker) GetAddressUtxo(address string, onlyConfirmed bool) ([]AddressUt r = append(r, AddressUtxo{ Txid: bchainTx.Txid, Vout: int32(i), - AmountSat: vout.ValueSat, - Amount: w.chainParser.AmountToDecimalString(&vout.ValueSat), + AmountSat: (*Amount)(&vout.ValueSat), }) } } @@ -734,7 +726,7 @@ func (w *Worker) GetAddressUtxo(address string, onlyConfirmed bool) ([]AddressUt outpoints := make([]bchain.Outpoint, 0, 8) err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, vout int32, isOutput bool) error { if isOutput { - outpoints = append(outpoints, bchain.Outpoint{txid, vout}) + outpoints = append(outpoints, bchain.Outpoint{Txid: txid, Vout: vout}) } return nil }) @@ -772,8 +764,7 @@ func (w *Worker) GetAddressUtxo(address string, onlyConfirmed bool) ([]AddressUt r = append(r, AddressUtxo{ Txid: o.Txid, Vout: o.Vout, - AmountSat: v, - Amount: w.chainParser.AmountToDecimalString(&v), + AmountSat: (*Amount)(&v), Height: int(ta.Height), Confirmations: bestheight - int(ta.Height) + 1, }) diff --git a/bchain/coins/eth/ethparser.go b/bchain/coins/eth/ethparser.go index b2b66c28..0e3afb7b 100644 --- a/bchain/coins/eth/ethparser.go +++ b/bchain/coins/eth/ethparser.go @@ -414,12 +414,11 @@ func GetErc20FromTx(tx *bchain.Tx) ([]Erc20Transfer, error) { // EthereumTxData contains ethereum specific transaction data type EthereumTxData struct { - Status int `json:"status"` // 1 OK, 0 Fail, -1 pending - Nonce uint64 `json:"nonce"` - GasLimit *big.Int `json:"gaslimit"` - GasUsed *big.Int `json:"gasused"` - GasPrice string `json:"gasprice"` - GasPriceNum *big.Int `json:"-"` + Status int `json:"status"` // 1 OK, 0 Fail, -1 pending + Nonce uint64 `json:"nonce"` + GasLimit *big.Int `json:"gaslimit"` + GasUsed *big.Int `json:"gasused"` + GasPrice *big.Int `json:"gasprice"` } // GetEthereumTxData returns EthereumTxData from bchain.Tx @@ -430,8 +429,7 @@ func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData { if csd.Tx != nil { etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce) etd.GasLimit, _ = hexutil.DecodeBig(csd.Tx.GasLimit) - etd.GasPriceNum, _ = hexutil.DecodeBig(csd.Tx.GasPrice) - etd.GasPrice = bchain.AmountToDecimalString(etd.GasPriceNum, EtherAmountDecimalPoint) + etd.GasPrice, _ = hexutil.DecodeBig(csd.Tx.GasPrice) } if csd.Receipt != nil { if csd.Receipt.Status == "0x1" { diff --git a/server/public.go b/server/public.go index 08c010cc..da7efa65 100644 --- a/server/public.go +++ b/server/public.go @@ -369,11 +369,12 @@ type TemplateData struct { func (s *PublicServer) parseTemplates() []*template.Template { templateFuncMap := template.FuncMap{ - "formatTime": formatTime, - "formatUnixTime": formatUnixTime, - "formatAmount": formatAmount, - "setTxToTemplateData": setTxToTemplateData, - "stringInSlice": stringInSlice, + "formatTime": formatTime, + "formatUnixTime": formatUnixTime, + "formatAmount": s.formatAmount, + "formatAmountWithDecimals": formatAmountWithDecimals, + "setTxToTemplateData": setTxToTemplateData, + "stringInSlice": stringInSlice, } t := make([]*template.Template, tplCount) t[errorTpl] = template.Must(template.New("error").Funcs(templateFuncMap).ParseFiles("./static/templates/error.html", "./static/templates/base.html")) @@ -403,11 +404,18 @@ func formatTime(t time.Time) string { // for now return the string as it is // in future could be used to do coin specific formatting -func formatAmount(a string) string { - if a == "" { +func (s *PublicServer) formatAmount(a *api.Amount) string { + if a == nil { return "0" } - return a + return s.chainParser.AmountToDecimalString((*big.Int)(a)) +} + +func formatAmountWithDecimals(a *api.Amount, d int) string { + if a == nil { + return "0" + } + return bchain.AmountToDecimalString((*big.Int)(a), d) } // called from template to support txdetail.html functionality diff --git a/server/socketio.go b/server/socketio.go index 131f31e1..92e8c25d 100644 --- a/server/socketio.go +++ b/server/socketio.go @@ -312,7 +312,7 @@ func txToResTx(tx *api.Tx) resTx { Script: &script, Sequence: int64(vin.Sequence), OutputIndex: int(vin.Vout), - Satoshis: vin.ValueSat.Int64(), + Satoshis: (*big.Int)(vin.ValueSat).Int64(), } if len(vin.Addresses) > 0 { a := vin.Addresses[0] @@ -325,7 +325,7 @@ func txToResTx(tx *api.Tx) resTx { vout := &tx.Vout[i] script := vout.ScriptPubKey.Hex output := txOutputs{ - Satoshis: vout.ValueSat.Int64(), + Satoshis: (*big.Int)(vout.ValueSat).Int64(), Script: &script, } if len(vout.ScriptPubKey.Addresses) > 0 { @@ -342,15 +342,15 @@ func txToResTx(tx *api.Tx) resTx { } return resTx{ BlockTimestamp: tx.Blocktime, - FeeSatoshis: tx.FeesSat.Int64(), + FeeSatoshis: (*big.Int)(tx.FeesSat).Int64(), Hash: tx.Txid, Height: h, Hex: tx.Hex, Inputs: inputs, - InputSatoshis: tx.ValueInSat.Int64(), + InputSatoshis: (*big.Int)(tx.ValueInSat).Int64(), Locktime: int(tx.Locktime), Outputs: outputs, - OutputSatoshis: tx.ValueOutSat.Int64(), + OutputSatoshis: (*big.Int)(tx.ValueOutSat).Int64(), Version: int(tx.Version), } } @@ -407,7 +407,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r ads[a] = hi } hi.InputIndexes = append(hi.InputIndexes, int(vin.N)) - totalSat.Sub(&totalSat, &vin.ValueSat) + totalSat.Sub(&totalSat, (*big.Int)(vin.ValueSat)) } } for i := range tx.Vout { @@ -420,7 +420,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r ads[a] = hi } hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N)) - totalSat.Add(&totalSat, &vout.ValueSat) + totalSat.Add(&totalSat, (*big.Int)(vout.ValueSat)) } } ahi := addressHistoryItem{} diff --git a/server/websocket.go b/server/websocket.go index d4ebf745..d676a3f7 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -91,7 +91,7 @@ func NewWebsocketServer(db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxC return s, nil } -// allow all origins, at least for now +// allow all origins func checkOrigin(r *http.Request) bool { return true } diff --git a/static/templates/address.html b/static/templates/address.html index ddd0f874..f9c34b4d 100644 --- a/static/templates/address.html +++ b/static/templates/address.html @@ -1,6 +1,6 @@ {{define "specific"}}{{$cs := .CoinShortcut}}{{$addr := .Address}}{{$data := .}}

{{if $addr.Erc20Contract}}Contract {{$addr.Erc20Contract.Name}} ({{$addr.Erc20Contract.Symbol}}){{else}}Address{{end}} - {{formatAmount $addr.Balance}} {{$cs}} + {{formatAmount $addr.BalanceSat}} {{$cs}}

{{$addr.AddrStr}} @@ -13,7 +13,7 @@ {{- if eq .ChainType 1 -}} Balance - {{formatAmount $addr.Balance}} {{$cs}} + {{formatAmount $addr.BalanceSat}} {{$cs}} Non-contract Transactions @@ -37,7 +37,7 @@ {{- range $et := $addr.Erc20Tokens -}} {{$et.Name}} - {{formatAmount $et.Balance}} {{$et.Symbol}} + {{formatAmountWithDecimals $et.BalanceSat $et.Decimals}} {{$et.Symbol}} {{$et.Txs}} {{- end -}} @@ -50,15 +50,15 @@ {{- else -}} Total Received - {{formatAmount $addr.TotalReceived}} {{$cs}} + {{formatAmount $addr.TotalReceivedSat}} {{$cs}} Total Sent - {{formatAmount $addr.TotalSent}} {{$cs}} + {{formatAmount $addr.TotalSentSat}} {{$cs}} Final Balance - {{formatAmount $addr.Balance}} {{$cs}} + {{formatAmount $addr.BalanceSat}} {{$cs}} No. Transactions @@ -83,7 +83,7 @@ Unconfirmed Balance - {{formatAmount $addr.UnconfirmedBalance}} {{$cs}} + {{formatAmount $addr.UnconfirmedBalanceSat}} {{$cs}} No. Transactions diff --git a/static/templates/tx.html b/static/templates/tx.html index 41ab7ed0..38c9f8a7 100644 --- a/static/templates/tx.html +++ b/static/templates/tx.html @@ -36,7 +36,7 @@ Value - {{formatAmount $tx.ValueOut}} {{$cs}} + {{formatAmount $tx.ValueOutSat}} {{$cs}} Gas Used / Limit @@ -49,17 +49,17 @@ {{- else -}} Total Input - {{formatAmount $tx.ValueIn}} {{$cs}} + {{formatAmount $tx.ValueInSat}} {{$cs}} Total Output - {{formatAmount $tx.ValueOut}} {{$cs}} + {{formatAmount $tx.ValueOutSat}} {{$cs}} {{- end -}} - {{- if $tx.Fees -}} + {{- if $tx.FeesSat -}} Fees - {{formatAmount $tx.Fees}} {{$cs}} + {{formatAmount $tx.FeesSat}} {{$cs}} {{end -}} diff --git a/static/templates/txdetail.html b/static/templates/txdetail.html index b69d2e86..970af3c6 100644 --- a/static/templates/txdetail.html +++ b/static/templates/txdetail.html @@ -26,7 +26,7 @@ {{- else -}} {{- if $vin.ScriptSig.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}} {{- end -}}{{- if $vin.Addresses -}} - {{formatAmount $vin.Value}} {{$cs}} + {{formatAmount $vin.ValueSat}} {{$cs}} {{- end -}} @@ -59,7 +59,7 @@ Unparsed address {{- end -}} - {{formatAmount $vout.Value}} {{$cs}} {{if $vout.Spent}}{{else -}} + {{formatAmount $vout.ValueSat}} {{$cs}} {{if $vout.Spent}}{{else -}} × {{- end -}} @@ -77,8 +77,8 @@
- {{- if $tx.Fees -}} - Fee: {{formatAmount $tx.Fees}} {{$cs}} + {{- if $tx.FeesSat -}} + Fee: {{formatAmount $tx.FeesSat}} {{$cs}} {{- end -}}
@@ -87,7 +87,7 @@ {{- else -}} Unconfirmed Transaction! {{- end -}} - {{formatAmount $tx.ValueOut}} {{$cs}} + {{formatAmount $tx.ValueOutSat}} {{$cs}}
diff --git a/static/templates/txdetail_ethereumtype.html b/static/templates/txdetail_ethereumtype.html index ec8f148e..e9a7f938 100644 --- a/static/templates/txdetail_ethereumtype.html +++ b/static/templates/txdetail_ethereumtype.html @@ -66,7 +66,7 @@
- {{formatAmount $tx.ValueOut}} {{$cs}} + {{formatAmount $tx.ValueOutSat}} {{$cs}}
{{- if $tx.Erc20Transfers -}} @@ -106,15 +106,15 @@ -
{{formatAmount $erc20.Tokens}} {{$erc20.Symbol}}
+
{{formatAmountWithDecimals $erc20.Tokens $erc20.Decimals}} {{$erc20.Symbol}}
{{- end -}}
{{- end -}}
- {{- if $tx.Fees -}} - Fee: {{formatAmount $tx.Fees}} {{$cs}} + {{- if $tx.FeesSat -}} + Fee: {{formatAmount $tx.FeesSat}} {{$cs}} {{- end -}}
@@ -123,7 +123,7 @@ {{- else -}} Unconfirmed Transaction! {{- end -}} - {{formatAmount $tx.ValueOut}} {{$cs}} + {{formatAmount $tx.ValueOutSat}} {{$cs}}