Skip to content

Commit

Permalink
services/horizon: Issue #3241, Include unauthorized assets on /assets (
Browse files Browse the repository at this point in the history
…#3454)

* Refactor test to use testify

* WIP - include unauthorized assets on /assets

* WIP - Flailing around with asset stats

* AssetStatNumAccounts -> AssetStatAccounts

* Passing tests for AssetStatsProcessor

* Rename migration to be after previous migrations

* use history.ExpAssetStat(Accounts|Balances), and make them serializable for the db

* bump the state verifier version? Is this right?

* Update history tests to use new asset stat columns

* Add a test to make sure state verifier fails when assets and accounts are unequal

* Mark the amount and num_accounts fields deprecated

* Update docs to remove old num_accounts and amount fields

* Fix go vet shadow warnings

* populate the actual AssetStatBalances to convert to amounts

* Fixing up staticcheck

* Remove defunct todos

* Update services/horizon/internal/ingest/processors/asset_stats_set.go

Co-authored-by: Bartek Nowotarski <[email protected]>

* Update services/horizon/internal/ingest/processors/asset_stats_set.go

Co-authored-by: Bartek Nowotarski <[email protected]>

* PR feedback

* Simplify big switch in AssetStatsProcessor

Co-authored-by: Bartek Nowotarski <[email protected]>
  • Loading branch information
Paul Bellamy and bartekn authored Mar 22, 2021
1 parent 181921f commit cad6852
Show file tree
Hide file tree
Showing 19 changed files with 978 additions and 171 deletions.
22 changes: 20 additions & 2 deletions protocols/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,12 @@ type AssetStat struct {
} `json:"_links"`

base.Asset
PT string `json:"paging_token"`
Amount string `json:"amount"`
PT string `json:"paging_token"`
Accounts AssetStatAccounts `json:"accounts"`
// Action needed in release: horizon-v3.0.0: deprecated field
Amount string `json:"amount"`
Balances AssetStatBalances `json:"balances"`
// Action needed in release: horizon-v3.0.0: deprecated field
NumAccounts int32 `json:"num_accounts"`
Flags AccountFlags `json:"flags"`
}
Expand All @@ -177,6 +181,20 @@ func (res AssetStat) PagingToken() string {
return res.PT
}

// AssetStatBalances represents the summarized balances for a single Asset
type AssetStatBalances struct {
Authorized string `json:"authorized"`
AuthorizedToMaintainLiabilities string `json:"authorized_to_maintain_liabilities"`
Unauthorized string `json:"unauthorized"`
}

// AssetStatAccounts represents the summarized acount numbers for a single Asset
type AssetStatAccounts struct {
Authorized int32 `json:"authorized"`
AuthorizedToMaintainLiabilities int32 `json:"authorized_to_maintain_liabilities"`
Unauthorized int32 `json:"unauthorized"`
}

// Balance represents an account's holdings for a single currency type
type Balance struct {
Balance string `json:"balance"`
Expand Down
2 changes: 2 additions & 0 deletions services/horizon/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ file. This project adheres to [Semantic Versioning](http://semver.org/).

* Add an endpoint which determines if Horizon is healthy enough to receive traffic ([3435](https://github.com/stellar/go/pull/3435)).
* Sanitize route regular expressions for Prometheus metrics ([3459](https://github.com/stellar/go/pull/3459)).
* Add asset stat summaries per trust-line flag category ([3454](https://github.com/stellar/go/pull/3454)).
- The `amount`, and `num_accounts` fields in `/assets` endpoint are deprecated. Fields will be removed in Horizon 3.0. You can find the same data under `balances.authorized`, and `accounts.authorized`, respectively.

## v2.0.0

Expand Down
119 changes: 105 additions & 14 deletions services/horizon/internal/actions/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"strings"
"testing"

"github.com/stretchr/testify/assert"

"github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/protocols/horizon/base"
"github.com/stellar/go/services/horizon/internal/db2/history"
Expand Down Expand Up @@ -123,10 +125,30 @@ func TestAssetStats(t *testing.T) {
AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4,
AssetIssuer: issuer.AccountID,
AssetCode: "USD",
Accounts: history.ExpAssetStatAccounts{
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
},
Balances: history.ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
},
Amount: "1",
NumAccounts: 2,
}
usdAssetStatResponse := horizon.AssetStat{
Accounts: horizon.AssetStatAccounts{
Authorized: usdAssetStat.Accounts.Authorized,
AuthorizedToMaintainLiabilities: usdAssetStat.Accounts.AuthorizedToMaintainLiabilities,
Unauthorized: usdAssetStat.Accounts.Unauthorized,
},
Balances: horizon.AssetStatBalances{
Authorized: "0.0000001",
AuthorizedToMaintainLiabilities: "0.0000002",
Unauthorized: "0.0000003",
},
Amount: "0.0000001",
NumAccounts: usdAssetStat.NumAccounts,
Asset: base.Asset{
Expand All @@ -142,10 +164,30 @@ func TestAssetStats(t *testing.T) {
AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4,
AssetIssuer: issuer.AccountID,
AssetCode: "ETHER",
Accounts: history.ExpAssetStatAccounts{
Authorized: 1,
AuthorizedToMaintainLiabilities: 2,
Unauthorized: 3,
},
Balances: history.ExpAssetStatBalances{
Authorized: "23",
AuthorizedToMaintainLiabilities: "46",
Unauthorized: "92",
},
Amount: "23",
NumAccounts: 1,
}
etherAssetStatResponse := horizon.AssetStat{
Accounts: horizon.AssetStatAccounts{
Authorized: etherAssetStat.Accounts.Authorized,
AuthorizedToMaintainLiabilities: etherAssetStat.Accounts.AuthorizedToMaintainLiabilities,
Unauthorized: etherAssetStat.Accounts.Unauthorized,
},
Balances: horizon.AssetStatBalances{
Authorized: "0.0000023",
AuthorizedToMaintainLiabilities: "0.0000046",
Unauthorized: "0.0000092",
},
Amount: "0.0000023",
NumAccounts: etherAssetStat.NumAccounts,
Asset: base.Asset{
Expand All @@ -161,10 +203,30 @@ func TestAssetStats(t *testing.T) {
AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4,
AssetIssuer: otherIssuer.AccountID,
AssetCode: "USD",
Accounts: history.ExpAssetStatAccounts{
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
},
Balances: history.ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
},
Amount: "1",
NumAccounts: 2,
}
otherUSDAssetStatResponse := horizon.AssetStat{
Accounts: horizon.AssetStatAccounts{
Authorized: otherUSDAssetStat.Accounts.Authorized,
AuthorizedToMaintainLiabilities: otherUSDAssetStat.Accounts.AuthorizedToMaintainLiabilities,
Unauthorized: otherUSDAssetStat.Accounts.Unauthorized,
},
Balances: horizon.AssetStatBalances{
Authorized: "0.0000001",
AuthorizedToMaintainLiabilities: "0.0000002",
Unauthorized: "0.0000003",
},
Amount: "0.0000001",
NumAccounts: otherUSDAssetStat.NumAccounts,
Asset: base.Asset{
Expand All @@ -182,10 +244,30 @@ func TestAssetStats(t *testing.T) {
AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4,
AssetIssuer: otherIssuer.AccountID,
AssetCode: "EUR",
Accounts: history.ExpAssetStatAccounts{
Authorized: 3,
AuthorizedToMaintainLiabilities: 4,
Unauthorized: 5,
},
Balances: history.ExpAssetStatBalances{
Authorized: "111",
AuthorizedToMaintainLiabilities: "222",
Unauthorized: "333",
},
Amount: "111",
NumAccounts: 3,
}
eurAssetStatResponse := horizon.AssetStat{
Accounts: horizon.AssetStatAccounts{
Authorized: eurAssetStat.Accounts.Authorized,
AuthorizedToMaintainLiabilities: eurAssetStat.Accounts.AuthorizedToMaintainLiabilities,
Unauthorized: eurAssetStat.Accounts.Unauthorized,
},
Balances: horizon.AssetStatBalances{
Authorized: "0.0000111",
AuthorizedToMaintainLiabilities: "0.0000222",
Unauthorized: "0.0000333",
},
Amount: "0.0000111",
NumAccounts: eurAssetStat.NumAccounts,
Asset: base.Asset{
Expand Down Expand Up @@ -311,23 +393,12 @@ func TestAssetStats(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
r := makeRequest(t, testCase.queryParams, map[string]string{}, q.Session)
results, err := handler.GetResourcePage(httptest.NewRecorder(), r)
if err != nil {
t.Fatalf("unexpected error %v", err)
}

if len(results) != len(testCase.expected) {
t.Fatalf(
"expectes results to have length %v but got %v",
len(results),
len(testCase.expected),
)
}
assert.NoError(t, err)

assert.Len(t, results, len(testCase.expected))
for i, item := range results {
assetStat := item.(horizon.AssetStat)
if assetStat != testCase.expected[i] {
t.Fatalf("expected %v but got %v", testCase.expected[i], assetStat)
}
assert.Equal(t, testCase.expected[i], assetStat)
}
})
}
Expand All @@ -344,6 +415,16 @@ func TestAssetStatsIssuerDoesNotExist(t *testing.T) {
AssetType: xdr.AssetTypeAssetTypeCreditAlphanum4,
AssetIssuer: "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H",
AssetCode: "USD",
Accounts: history.ExpAssetStatAccounts{
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
},
Balances: history.ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
},
Amount: "1",
NumAccounts: 2,
}
Expand All @@ -356,6 +437,16 @@ func TestAssetStatsIssuerDoesNotExist(t *testing.T) {
tt.Assert.NoError(err)

expectedAssetStatResponse := horizon.AssetStat{
Accounts: horizon.AssetStatAccounts{
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
},
Balances: horizon.AssetStatBalances{
Authorized: "0.0000001",
AuthorizedToMaintainLiabilities: "0.0000002",
Unauthorized: "0.0000003",
},
Amount: "0.0000001",
NumAccounts: usdAssetStat.NumAccounts,
Asset: base.Asset{
Expand Down
2 changes: 2 additions & 0 deletions services/horizon/internal/db2/history/asset_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func assetStatToMap(assetStat ExpAssetStat) map[string]interface{} {
"asset_type": assetStat.AssetType,
"asset_code": assetStat.AssetCode,
"asset_issuer": assetStat.AssetIssuer,
"accounts": assetStat.Accounts,
"balances": assetStat.Balances,
"amount": assetStat.Amount,
"num_accounts": assetStat.NumAccounts,
}
Expand Down
Loading

0 comments on commit cad6852

Please sign in to comment.