Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

services/horizon: Issue #3241, Include unauthorized assets on /assets #3454

Merged
merged 20 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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