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/internal/actions: Update payload for "Accounts For Signers" end-point. #1876

Merged
merged 4 commits into from
Oct 25, 2019
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion services/horizon/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bumps. A breaking change will get clearly notified in this log.
The following request will return all accounts who have a trustline to the asset identified by `asset_type=credit_alphanum4`, `asset_code=COP`, and `asset_issuer=GC2GFGZ5CZCFCDJSQF3YYEAYBOS3ZREXJSPU7LUJ7JU3LP3BQNHY7YKS`:

`/accounts?asset_type=credit_alphanum4&asset_code=COP&asset_issuer=GC2GFGZ5CZCFCDJSQF3YYEAYBOS3ZREXJSPU7LUJ7JU3LP3BQNHY7YKS`

* Update payload in experimental "Accounts For Signers" end-point to return an account resource. ([#1876](https://github.com/stellar/go/pull/1876))

## v0.22.1

Expand Down
68 changes: 32 additions & 36 deletions services/horizon/internal/actions/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,58 +147,54 @@ func (handler GetAccountsHandler) GetResourcePage(
return nil, err
}

var records []history.AccountEntry

if len(qp.Signer) > 0 {
records, err := historyQ.AccountsForSigner(qp.Signer, pq)
records, err = historyQ.AccountEntriesForSigner(qp.Signer, pq)
if err != nil {
return nil, errors.Wrap(err, "loading account records")
}

for _, record := range records {
var res protocol.AccountSigner
resourceadapter.PopulateAccountSigner(ctx, &res, record)
accounts = append(accounts, res)
}
} else {
records, err := historyQ.AccountsForAsset(*qp.Asset(), pq)
records, err = historyQ.AccountsForAsset(*qp.Asset(), pq)
if err != nil {
return nil, errors.Wrap(err, "loading account records")
}
}

if len(records) == 0 {
// early return
return accounts, nil
}
if len(records) == 0 {
// early return
return accounts, nil
}
abuiles marked this conversation as resolved.
Show resolved Hide resolved

accountIDs := make([]string, 0, len(records))
for _, record := range records {
accountIDs = append(accountIDs, record.AccountID)
}
accountIDs := make([]string, 0, len(records))
for _, record := range records {
accountIDs = append(accountIDs, record.AccountID)
}

signers, err := handler.loadSigners(historyQ, accountIDs)
if err != nil {
return nil, err
}
signers, err := handler.loadSigners(historyQ, accountIDs)
if err != nil {
return nil, err
}

trustlines, err := handler.loadTrustlines(historyQ, accountIDs)
if err != nil {
return nil, err
}
trustlines, err := handler.loadTrustlines(historyQ, accountIDs)
if err != nil {
return nil, err
}

data, err := handler.loadData(historyQ, accountIDs)
if err != nil {
return nil, err
}
data, err := handler.loadData(historyQ, accountIDs)
if err != nil {
return nil, err
}

for _, record := range records {
var res protocol.Account
s := signers[record.AccountID]
t := trustlines[record.AccountID]
d := data[record.AccountID]
for _, record := range records {
var res protocol.Account
s := signers[record.AccountID]
t := trustlines[record.AccountID]
d := data[record.AccountID]

resourceadapter.PopulateAccountEntry(ctx, &res, record, d, s, t)
resourceadapter.PopulateAccountEntry(ctx, &res, record, d, s, t)

accounts = append(accounts, res)
}
accounts = append(accounts, res)
}

return accounts, nil
Expand Down
117 changes: 80 additions & 37 deletions services/horizon/internal/actions/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ var (
},
},
}

account3 = xdr.AccountEntry{
AccountId: xdr.MustAddress(signer),
Balance: 50000,
SeqNum: 648736,
NumSubEntries: 10,
Flags: 2,
Thresholds: xdr.Thresholds{5, 6, 7, 8},
Ext: xdr.AccountEntryExt{
V: 1,
V1: &xdr.AccountEntryV1{
Liabilities: xdr.Liabilities{
Buying: 30,
Selling: 40,
},
},
},
}

eurTrustLine = xdr.TrustLineEntry{
AccountId: xdr.MustAddress(accountOne),
Asset: euro,
Expand Down Expand Up @@ -106,6 +125,34 @@ var (
DataName: "test data2",
DataValue: []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
}

accountSigners = []history.AccountSigner{
history.AccountSigner{
Account: accountOne,
Signer: accountOne,
Weight: 1,
},
history.AccountSigner{
Account: accountTwo,
Signer: accountTwo,
Weight: 1,
},
history.AccountSigner{
Account: accountOne,
Signer: signer,
Weight: 1,
},
history.AccountSigner{
Account: accountTwo,
Signer: signer,
Weight: 2,
},
history.AccountSigner{
Account: signer,
Signer: signer,
Weight: 3,
},
}
)

func TestAccountInfo(t *testing.T) {
Expand Down Expand Up @@ -156,9 +203,14 @@ func TestGetAccountsHandlerPageResultsBySigner(t *testing.T) {
q := &history.Q{tt.HorizonSession()}
handler := &GetAccountsHandler{}

rows := accountSigners()
_, err := q.InsertAccount(account1, 1234)
tt.Assert.NoError(err)
_, err = q.InsertAccount(account2, 1234)
tt.Assert.NoError(err)
_, err = q.InsertAccount(account3, 1234)
tt.Assert.NoError(err)

for _, row := range rows {
for _, row := range accountSigners {
q.CreateAccountSigner(row.Account, row.Signer, row.Weight)
}

Expand All @@ -177,20 +229,27 @@ func TestGetAccountsHandlerPageResultsBySigner(t *testing.T) {
tt.Assert.NoError(err)
tt.Assert.Equal(3, len(records))

for i, row := range rows {
result := records[i].(protocol.AccountSigner)
tt.Assert.Equal(row.Account, result.AccountID)
tt.Assert.Equal(row.Signer, result.Signer.Key)
tt.Assert.Equal(row.Weight, result.Signer.Weight)
want := map[string]bool{
accountOne: true,
accountTwo: true,
signer: true,
}

for _, row := range records {
result := row.(protocol.Account)
tt.Assert.True(want[result.AccountID])
delete(want, result.AccountID)
}

tt.Assert.Empty(want)

records, err = handler.GetResourcePage(
httptest.NewRecorder(),
makeRequest(
t,
map[string]string{
"signer": "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU",
"cursor": "GABGMPEKKDWR2WFH5AJOZV5PDKLJEHGCR3Q24ALETWR5H3A7GI3YTS7V",
"signer": signer,
"cursor": accountOne,
},
map[string]string{},
q.Session,
Expand All @@ -200,12 +259,18 @@ func TestGetAccountsHandlerPageResultsBySigner(t *testing.T) {
tt.Assert.NoError(err)
tt.Assert.Equal(2, len(records))

for i, row := range rows[1:] {
result := records[i].(protocol.AccountSigner)
tt.Assert.Equal(row.Account, result.AccountID)
tt.Assert.Equal(row.Signer, result.Signer.Key)
tt.Assert.Equal(row.Weight, result.Signer.Weight)
want = map[string]bool{
accountTwo: true,
signer: true,
}

for _, row := range records {
result := row.(protocol.Account)
tt.Assert.True(want[result.AccountID])
delete(want, result.AccountID)
}

tt.Assert.Empty(want)
}

func TestGetAccountsHandlerPageResultsByAsset(t *testing.T) {
Expand All @@ -221,9 +286,7 @@ func TestGetAccountsHandlerPageResultsByAsset(t *testing.T) {
_, err = q.InsertAccount(account2, 1234)
tt.Assert.NoError(err)

rows := accountSigners()

for _, row := range rows {
for _, row := range accountSigners {
_, err = q.CreateAccountSigner(row.Account, row.Signer, row.Weight)
tt.Assert.NoError(err)
}
Expand Down Expand Up @@ -355,23 +418,3 @@ func TestGetAccountsHandlerInvalidParams(t *testing.T) {
})
}
}

func accountSigners() []history.AccountSigner {
return []history.AccountSigner{
history.AccountSigner{
Account: accountOne,
Signer: signer,
Weight: 1,
},
history.AccountSigner{
Account: accountTwo,
Signer: signer,
Weight: 2,
},
history.AccountSigner{
Account: accountThree,
Signer: signer,
Weight: 3,
},
}
}
25 changes: 24 additions & 1 deletion services/horizon/internal/db2/history/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (q *Q) RemoveAccount(accountID string) (int64, error) {
return result.RowsAffected()
}

// AccountSignersForAsset returns a list of `AccountSigner` rows who are trustee to an
// AccountsForAsset returns a list of `AccountEntry` rows who are trustee to an
// asset
func (q *Q) AccountsForAsset(asset xdr.Asset, page db2.PageQuery) ([]AccountEntry, error) {
var assetType, code, issuer string
Expand Down Expand Up @@ -147,6 +147,29 @@ func (q *Q) AccountsForAsset(asset xdr.Asset, page db2.PageQuery) ([]AccountEntr
return results, nil
}

// AccountEntriesForSigner returns a list of `AccountEntry` rows for a given signer
func (q *Q) AccountEntriesForSigner(signer string, page db2.PageQuery) ([]AccountEntry, error) {
sql := sq.
Select("accounts.*").
From("accounts").
Join("accounts_signers ON accounts.account_id = accounts_signers.account").
Where(map[string]interface{}{
"accounts_signers.signer": signer,
})

sql, err := page.ApplyToUsingCursor(sql, "accounts_signers.account", page.Cursor)
if err != nil {
return nil, errors.Wrap(err, "could not apply query to page")
}

var results []AccountEntry
if err := q.Select(&results, sql); err != nil {
return nil, errors.Wrap(err, "could not run select query")
}

return results, nil
}

var selectAccounts = sq.Select(`
account_id,
balance,
Expand Down
Loading