From 2c3af5129e359346938853bb4d3d7638fdb5c09b Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Mon, 7 Jan 2019 15:45:00 +0100 Subject: [PATCH] Generalize tokens instead of ERC20 tokens in API --- api/types.go | 68 +++++++++++++++++++---------------- api/typesv1.go | 4 +-- api/worker.go | 59 +++++++++++++++--------------- server/public_test.go | 2 +- static/templates/address.html | 28 ++++++++------- 5 files changed, 88 insertions(+), 73 deletions(-) diff --git a/api/types.go b/api/types.go index 349cbfcc..6dc49bae 100644 --- a/api/types.go +++ b/api/types.go @@ -104,27 +104,34 @@ type Vout struct { Type string `json:"type,omitempty"` } -// Erc20Token contains info about ERC20 token held by an address -type Erc20Token struct { - Contract string `json:"contract"` - Transfers int `json:"transfers"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Decimals int `json:"decimals"` - BalanceSat *Amount `json:"balance,omitempty"` - ContractIndex string `json:"-"` +// TokenType specifies type of token +type TokenType string + +// ERC20TokenType is Ethereum ERC20 token +const ERC20TokenType TokenType = "ERC20" + +// Token contains info about tokens held by an address +type Token struct { + Type TokenType `json:"type"` + Contract string `json:"contract"` + Transfers int `json:"transfers"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals int `json:"decimals"` + BalanceSat *Amount `json:"balance,omitempty"` + ContractIndex string `json:"-"` } // TokenTransfer contains info about a token transfer done in a transaction type TokenTransfer struct { - Type string `json:"type"` - From string `json:"from"` - To string `json:"to"` - Token string `json:"token"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Decimals int `json:"decimals"` - Value *Amount `json:"value"` + Type TokenType `json:"type"` + From string `json:"from"` + To string `json:"to"` + Token string `json:"token"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals int `json:"decimals"` + Value *Amount `json:"value"` } // EthereumSpecific contains ethereum specific transaction data @@ -186,19 +193,20 @@ type AddressFilter struct { // Address holds information about address and its transactions type Address struct { Paging - AddrStr string `json:"addrStr"` - 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:"transactions,omitempty"` - Txids []string `json:"txids,omitempty"` - Nonce string `json:"nonce,omitempty"` - Erc20Contract *bchain.Erc20Contract `json:"erc20contract,omitempty"` - Erc20Tokens []Erc20Token `json:"erc20tokens,omitempty"` - Filter string `json:"-"` + AddrStr string `json:"addrStr"` + BalanceSat *Amount `json:"balance"` + TotalReceivedSat *Amount `json:"totalReceived,omitempty"` + TotalSentSat *Amount `json:"totalSent,omitempty"` + UnconfirmedBalanceSat *Amount `json:"unconfirmedBalance"` + UnconfirmedTxs int `json:"unconfirmedTxs"` + Txs int `json:"txs"` + NonTokenTxs int `json:"nontokenTxs,omitempty"` + Transactions []*Tx `json:"transactions,omitempty"` + Txids []string `json:"txids,omitempty"` + Nonce string `json:"nonce,omitempty"` + Tokens []Token `json:"tokens,omitempty"` + Erc20Contract *bchain.Erc20Contract `json:"erc20contract,omitempty"` + Filter string `json:"-"` } // AddressUtxo holds information about address and its transactions diff --git a/api/typesv1.go b/api/typesv1.go index 301f5724..d80e0372 100644 --- a/api/typesv1.go +++ b/api/typesv1.go @@ -184,10 +184,10 @@ func (w *Worker) AddressToV1(a *Address) *AddressV1 { TotalReceived: a.TotalReceivedSat.DecimalString(d), TotalSent: a.TotalSentSat.DecimalString(d), Transactions: w.transactionsToV1(a.Transactions), - TxApperances: a.TxApperances, + TxApperances: a.Txs, Txids: a.Txids, UnconfirmedBalance: a.UnconfirmedBalanceSat.DecimalString(d), - UnconfirmedTxApperances: a.UnconfirmedTxApperances, + UnconfirmedTxApperances: a.UnconfirmedTxs, } } diff --git a/api/worker.go b/api/worker.go index ae936817..846c811a 100644 --- a/api/worker.go +++ b/api/worker.go @@ -242,7 +242,7 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32, erc20c = &bchain.Erc20Contract{Name: e.Contract} } tokens[i] = TokenTransfer{ - Type: "ERC20", + Type: ERC20TokenType, Token: e.Contract, From: e.From, To: e.To, @@ -460,16 +460,16 @@ func computePaging(count, page, itemsOnPage int) (Paging, int, int, int) { }, from, to, page } -func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescriptor, option GetAddressOption, filter *AddressFilter) (*db.AddrBalance, []Erc20Token, *bchain.Erc20Contract, uint64, error) { +func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescriptor, option GetAddressOption, filter *AddressFilter) (*db.AddrBalance, []Token, *bchain.Erc20Contract, uint64, int, error) { var ( ba *db.AddrBalance - erc20t []Erc20Token + tokens []Token ci *bchain.Erc20Contract n uint64 ) ca, err := w.db.GetAddrDescContracts(addrDesc) if err != nil { - return nil, nil, nil, 0, NewAPIError(fmt.Sprintf("Address not found, %v", err), true) + return nil, nil, nil, 0, 0, NewAPIError(fmt.Sprintf("Address not found, %v", err), true) } if ca != nil { ba = &db.AddrBalance{ @@ -478,23 +478,23 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto var b *big.Int b, err = w.chain.EthereumTypeGetBalance(addrDesc) if err != nil { - return nil, nil, nil, 0, errors.Annotatef(err, "EthereumTypeGetBalance %v", addrDesc) + return nil, nil, nil, 0, 0, errors.Annotatef(err, "EthereumTypeGetBalance %v", addrDesc) } if b != nil { ba.BalanceSat = *b } n, err = w.chain.EthereumTypeGetNonce(addrDesc) if err != nil { - return nil, nil, nil, 0, errors.Annotatef(err, "EthereumTypeGetNonce %v", addrDesc) + return nil, nil, nil, 0, 0, errors.Annotatef(err, "EthereumTypeGetNonce %v", addrDesc) } var filterDesc bchain.AddressDescriptor if filter.Contract != "" { filterDesc, err = w.chainParser.GetAddrDescFromAddress(filter.Contract) if err != nil { - return nil, nil, nil, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true) + return nil, nil, nil, 0, 0, NewAPIError(fmt.Sprintf("Invalid contract filter, %v", err), true) } } - erc20t = make([]Erc20Token, len(ca.Contracts)) + tokens = make([]Token, len(ca.Contracts)) var j int for i, c := range ca.Contracts { if len(filterDesc) > 0 { @@ -506,7 +506,7 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto } ci, err := w.chain.EthereumTypeGetErc20ContractInfo(c.Contract) if err != nil { - return nil, nil, nil, 0, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", c.Contract) + return nil, nil, nil, 0, 0, errors.Annotatef(err, "EthereumTypeGetErc20ContractInfo %v", c.Contract) } if ci == nil { ci = &bchain.Erc20Contract{} @@ -526,7 +526,8 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto } else { b = nil } - erc20t[j] = Erc20Token{ + tokens[j] = Token{ + Type: ERC20TokenType, BalanceSat: (*Amount)(b), Contract: ci.Contract, Name: ci.Name, @@ -537,13 +538,13 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto } j++ } - erc20t = erc20t[:j] + tokens = tokens[:j] ci, err = w.chain.EthereumTypeGetErc20ContractInfo(addrDesc) if err != nil { - return nil, nil, nil, 0, err + return nil, nil, nil, 0, 0, err } } - return ba, erc20t, ci, n, nil + return ba, tokens, ci, n, int(ca.NonContractTxs), nil } // GetAddress computes address value and gets transactions for given address @@ -559,7 +560,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA } var ( ba *db.AddrBalance - erc20t []Erc20Token + tokens []Token erc20c *bchain.Erc20Contract txm []string txs []*Tx @@ -568,10 +569,11 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA uBalSat big.Int totalReceived, totalSent *big.Int nonce string + nonTokenTxs int ) if w.chainType == bchain.ChainEthereumType { var n uint64 - ba, erc20t, erc20c, n, err = w.getEthereumTypeAddressBalances(addrDesc, option, filter) + ba, tokens, erc20c, n, nonTokenTxs, err = w.getEthereumTypeAddressBalances(addrDesc, option, filter) if err != nil { return nil, err } @@ -684,19 +686,20 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA totalSent = &ba.SentSat } r := &Address{ - Paging: pg, - AddrStr: address, - BalanceSat: (*Amount)(&ba.BalanceSat), - TotalReceivedSat: (*Amount)(totalReceived), - TotalSentSat: (*Amount)(totalSent), - TxApperances: int(ba.Txs), - UnconfirmedBalanceSat: (*Amount)(&uBalSat), - UnconfirmedTxApperances: len(txm), - Transactions: txs, - Txids: txids, - Erc20Contract: erc20c, - Erc20Tokens: erc20t, - Nonce: nonce, + Paging: pg, + AddrStr: address, + BalanceSat: (*Amount)(&ba.BalanceSat), + TotalReceivedSat: (*Amount)(totalReceived), + TotalSentSat: (*Amount)(totalSent), + Txs: int(ba.Txs), + NonTokenTxs: nonTokenTxs, + UnconfirmedBalanceSat: (*Amount)(&uBalSat), + UnconfirmedTxs: len(txm), + Transactions: txs, + Txids: txids, + Tokens: tokens, + Erc20Contract: erc20c, + Nonce: nonce, } glog.Info("GetAddress ", address, " finished in ", time.Since(start)) return r, nil diff --git a/server/public_test.go b/server/public_test.go index 3de922bf..de570af2 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -433,7 +433,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"page":1,"totalPages":1,"itemsOnPage":1000,"addrStr":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","balance":"0","totalReceived":"1234567890123","totalSent":"1234567890123","unconfirmedBalance":"0","unconfirmedTxApperances":0,"txApperances":2,"txids":["7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75"]}`, + `{"page":1,"totalPages":1,"itemsOnPage":1000,"addrStr":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","balance":"0","totalReceived":"1234567890123","totalSent":"1234567890123","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"txids":["7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75"]}`, }, }, { diff --git a/static/templates/address.html b/static/templates/address.html index 5f9ae79a..f479cb53 100644 --- a/static/templates/address.html +++ b/static/templates/address.html @@ -17,13 +17,17 @@ Transactions - {{$addr.TxApperances}} + {{$addr.Txs}} + + + Non-contract Transactions + {{$addr.NonTokenTxs}} Nonce {{$addr.Nonce}} - {{- if $addr.Erc20Tokens -}} + {{- if $addr.Tokens -}} ERC20 Tokens @@ -34,11 +38,11 @@ Tokens Transfers - {{- range $et := $addr.Erc20Tokens -}} + {{- range $t := $addr.Tokens -}} - {{$et.Name}} - {{formatAmountWithDecimals $et.BalanceSat $et.Decimals}} {{$et.Symbol}} - {{$et.Transfers}} + {{if $t.Contract}}{{$t.Name}}{{else}}{{$t.Name}}{{end}} + {{formatAmountWithDecimals $t.BalanceSat $t.Decimals}} {{$t.Symbol}} + {{$t.Transfers}} {{- end -}} @@ -62,7 +66,7 @@ No. Transactions - {{$addr.TxApperances}} + {{$addr.Txs}} {{- end -}} @@ -76,7 +80,7 @@ -{{- if $addr.UnconfirmedTxApperances -}} +{{- if $addr.UnconfirmedTxs -}}

Unconfirmed

@@ -87,7 +91,7 @@ - +
No. Transactions{{$addr.UnconfirmedTxApperances}}{{$addr.UnconfirmedTxs}}
@@ -99,10 +103,10 @@ - {{- if $addr.Erc20Tokens -}} + {{- if $addr.Tokens -}} - {{- range $et := $addr.Erc20Tokens -}} - + {{- range $t := $addr.Tokens -}} + {{- end -}} {{- end -}}