Skip to content

Commit

Permalink
Add resource adapter for history.AccountEntry. (#1859)
Browse files Browse the repository at this point in the history
  • Loading branch information
abuiles authored Oct 21, 2019
1 parent 717c5ab commit b0804f1
Show file tree
Hide file tree
Showing 13 changed files with 585 additions and 0 deletions.
6 changes: 6 additions & 0 deletions protocols/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ type Account struct {
Balances []Balance `json:"balances"`
Signers []Signer `json:"signers"`
Data map[string]string `json:"data"`
PT string `json:"paging_token"`
}

// PagingToken implementation for hal.Pageable
func (res Account) PagingToken() string {
return res.PT
}

// GetAccountID returns the Stellar account ID. This is to satisfy the
Expand Down
30 changes: 30 additions & 0 deletions services/horizon/internal/db2/history/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/stellar/go/services/horizon/internal/test"
"github.com/stretchr/testify/assert"
)

func TestAccountQueries(t *testing.T) {
Expand All @@ -19,3 +20,32 @@ func TestAccountQueries(t *testing.T) {
tt.Assert.Len(acs, 4)
}
}

func TestIsAuthRequired(t *testing.T) {
tt := assert.New(t)

account := AccountEntry{Flags: 1}
tt.True(account.IsAuthRequired())

account = AccountEntry{Flags: 0}
tt.False(account.IsAuthRequired())
}

func TestIsAuthRevocable(t *testing.T) {
tt := assert.New(t)

account := AccountEntry{Flags: 2}
tt.True(account.IsAuthRevocable())

account = AccountEntry{Flags: 1}
tt.False(account.IsAuthRevocable())
}
func TestIsAuthImmutable(t *testing.T) {
tt := assert.New(t)

account := AccountEntry{Flags: 4}
tt.True(account.IsAuthImmutable())

account = AccountEntry{Flags: 0}
tt.False(account.IsAuthImmutable())
}
18 changes: 18 additions & 0 deletions services/horizon/internal/db2/history/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ import (
"github.com/stellar/go/xdr"
)

// IsAuthRequired returns true if the account has the "AUTH_REQUIRED" option
// turned on.
func (account AccountEntry) IsAuthRequired() bool {
return xdr.AccountFlags(account.Flags).IsAuthRequired()
}

// IsAuthRevocable returns true if the account has the "AUTH_REVOCABLE" option
// turned on.
func (account AccountEntry) IsAuthRevocable() bool {
return xdr.AccountFlags(account.Flags).IsAuthRevocable()
}

// IsAuthImmutable returns true if the account has the "AUTH_IMMUTABLE" option
// turned on.
func (account AccountEntry) IsAuthImmutable() bool {
return xdr.AccountFlags(account.Flags).IsAuthImmutable()
}

func (q *Q) CountAccounts() (int, error) {
sql := sq.Select("count(*)").From("accounts")

Expand Down
6 changes: 6 additions & 0 deletions services/horizon/internal/db2/history/trust_lines.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import (
"github.com/stellar/go/xdr"
)

// IsAuthorized returns true if issuer has authorized account to perform
// transactions with its credit
func (trustLine TrustLine) IsAuthorized() bool {
return xdr.TrustLineFlags(trustLine.Flags).IsAuthorized()
}

func (q *Q) CountTrustLines() (int, error) {
sql := sq.Select("count(*)").From("trust_lines")

Expand Down
12 changes: 12 additions & 0 deletions services/horizon/internal/db2/history/trust_lines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ var (
}
)

func TestIsAuthorized(t *testing.T) {
tt := assert.New(t)
tl := TrustLine{
Flags: 1,
}
tt.True(tl.IsAuthorized())

tl = TrustLine{
Flags: 0,
}
tt.False(tl.IsAuthorized())
}
func TestInsertTrustLine(t *testing.T) {
tt := test.Start(t)
defer tt.Finish()
Expand Down
103 changes: 103 additions & 0 deletions services/horizon/internal/resourceadapter/account_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package resourceadapter

import (
"context"
"encoding/base64"
"fmt"
"strconv"

protocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/services/horizon/internal/db2/history"
"github.com/stellar/go/services/horizon/internal/httpx"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/render/hal"
"github.com/stellar/go/xdr"
)

// PopulateAccountEntry fills out the resource's fields
func PopulateAccountEntry(
ctx context.Context,
dest *protocol.Account,
account history.AccountEntry,
accountData []history.Data,
accountSigners []history.AccountSigner,
trustLines []history.TrustLine,
) error {
dest.ID = account.AccountID
dest.PT = account.AccountID
dest.AccountID = account.AccountID
dest.Sequence = strconv.FormatInt(account.SequenceNumber, 10)
dest.SubentryCount = int32(account.NumSubEntries)
dest.InflationDestination = account.InflationDestination
dest.HomeDomain = account.HomeDomain
dest.LastModifiedLedger = account.LastModifiedLedger

dest.Flags.AuthRequired = account.IsAuthRequired()
dest.Flags.AuthRevocable = account.IsAuthRevocable()
dest.Flags.AuthImmutable = account.IsAuthImmutable()

dest.Thresholds.LowThreshold = account.ThresholdLow
dest.Thresholds.MedThreshold = account.ThresholdMedium
dest.Thresholds.HighThreshold = account.ThresholdHigh

// populate balances
dest.Balances = make([]protocol.Balance, len(trustLines)+1)
for i, tl := range trustLines {
err := PopulateHistoryBalance(&dest.Balances[i], tl)
if err != nil {
return errors.Wrap(err, "populating balance")
}
}

// add native balance
err := PopulateNativeBalance(
&dest.Balances[len(dest.Balances)-1],
xdr.Int64(account.Balance),
xdr.Int64(account.BuyingLiabilities),
xdr.Int64(account.SellingLiabilities),
)
if err != nil {
return errors.Wrap(err, "populating native balance")
}

// populate data
dest.Data = make(map[string]string)
for _, d := range accountData {
dest.Data[d.Name] = base64.StdEncoding.EncodeToString(d.Value)
}

masterKeyIncluded := false

// populate signers
dest.Signers = make([]protocol.Signer, len(accountSigners))
for i, signer := range accountSigners {
dest.Signers[i].Weight = signer.Weight
dest.Signers[i].Key = signer.Signer
dest.Signers[i].Type = protocol.MustKeyTypeFromAddress(signer.Signer)

if account.AccountID == signer.Signer {
masterKeyIncluded = true
}
}

if !masterKeyIncluded {
dest.Signers = append(dest.Signers, protocol.Signer{
Weight: int32(account.MasterWeight),
Key: account.AccountID,
Type: protocol.MustKeyTypeFromAddress(account.AccountID),
})
}

lb := hal.LinkBuilder{httpx.BaseURL(ctx)}
self := fmt.Sprintf("/accounts/%s", account.AccountID)
dest.Links.Self = lb.Link(self)
dest.Links.Transactions = lb.PagedLink(self, "transactions")
dest.Links.Operations = lb.PagedLink(self, "operations")
dest.Links.Payments = lb.PagedLink(self, "payments")
dest.Links.Effects = lb.PagedLink(self, "effects")
dest.Links.Offers = lb.PagedLink(self, "offers")
dest.Links.Trades = lb.PagedLink(self, "trades")
dest.Links.Data = lb.Link(self, "data/{key}")
dest.Links.Data.PopulateTemplated()
return nil
}
Loading

0 comments on commit b0804f1

Please sign in to comment.