From b0804f184f0635a9a6c8686ebd90d26501823e37 Mon Sep 17 00:00:00 2001 From: Adolfo Builes Date: Mon, 21 Oct 2019 17:05:41 -0500 Subject: [PATCH] Add resource adapter for history.AccountEntry. (#1859) --- protocols/horizon/main.go | 6 + .../internal/db2/history/account_test.go | 30 +++ .../horizon/internal/db2/history/accounts.go | 18 ++ .../internal/db2/history/trust_lines.go | 6 + .../internal/db2/history/trust_lines_test.go | 12 + .../internal/resourceadapter/account_entry.go | 103 ++++++++ .../resourceadapter/account_entry_test.go | 243 ++++++++++++++++++ .../internal/resourceadapter/balance.go | 19 ++ .../internal/resourceadapter/balance_test.go | 44 ++++ xdr/account_flags.go | 19 ++ xdr/account_flags_test.go | 57 ++++ xdr/trust_line_flags.go | 7 + xdr/trust_line_flags_test.go | 21 ++ 13 files changed, 585 insertions(+) create mode 100644 services/horizon/internal/resourceadapter/account_entry.go create mode 100644 services/horizon/internal/resourceadapter/account_entry_test.go create mode 100644 xdr/account_flags.go create mode 100644 xdr/account_flags_test.go create mode 100644 xdr/trust_line_flags.go create mode 100644 xdr/trust_line_flags_test.go diff --git a/protocols/horizon/main.go b/protocols/horizon/main.go index 687fffb5e3..9b31ae75e4 100644 --- a/protocols/horizon/main.go +++ b/protocols/horizon/main.go @@ -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 diff --git a/services/horizon/internal/db2/history/account_test.go b/services/horizon/internal/db2/history/account_test.go index 0904fb4d38..97af9a8469 100644 --- a/services/horizon/internal/db2/history/account_test.go +++ b/services/horizon/internal/db2/history/account_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stellar/go/services/horizon/internal/test" + "github.com/stretchr/testify/assert" ) func TestAccountQueries(t *testing.T) { @@ -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()) +} diff --git a/services/horizon/internal/db2/history/accounts.go b/services/horizon/internal/db2/history/accounts.go index 410dc97eac..85ed57cd23 100644 --- a/services/horizon/internal/db2/history/accounts.go +++ b/services/horizon/internal/db2/history/accounts.go @@ -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") diff --git a/services/horizon/internal/db2/history/trust_lines.go b/services/horizon/internal/db2/history/trust_lines.go index 3c52a46818..593c908947 100644 --- a/services/horizon/internal/db2/history/trust_lines.go +++ b/services/horizon/internal/db2/history/trust_lines.go @@ -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") diff --git a/services/horizon/internal/db2/history/trust_lines_test.go b/services/horizon/internal/db2/history/trust_lines_test.go index 30317efe93..cd17875442 100644 --- a/services/horizon/internal/db2/history/trust_lines_test.go +++ b/services/horizon/internal/db2/history/trust_lines_test.go @@ -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() diff --git a/services/horizon/internal/resourceadapter/account_entry.go b/services/horizon/internal/resourceadapter/account_entry.go new file mode 100644 index 0000000000..f8f551ad27 --- /dev/null +++ b/services/horizon/internal/resourceadapter/account_entry.go @@ -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 +} diff --git a/services/horizon/internal/resourceadapter/account_entry_test.go b/services/horizon/internal/resourceadapter/account_entry_test.go new file mode 100644 index 0000000000..1455b07e8b --- /dev/null +++ b/services/horizon/internal/resourceadapter/account_entry_test.go @@ -0,0 +1,243 @@ +package resourceadapter + +import ( + "encoding/base64" + "encoding/json" + "strconv" + "testing" + + "github.com/stellar/go/amount" + . "github.com/stellar/go/protocols/horizon" + protocol "github.com/stellar/go/protocols/horizon" + "github.com/stellar/go/services/horizon/internal/assets" + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/support/test" + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" +) + +var ( + accountID = xdr.MustAddress("GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB") + + data = []history.Data{ + history.Data{ + AccountID: accountID.Address(), + Name: "test", + Value: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + LastModifiedLedger: 1, + }, + history.Data{ + AccountID: accountID.Address(), + Name: "test2", + Value: []byte{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, + LastModifiedLedger: 2, + }, + } + + inflationDest = xdr.MustAddress("GBUH7T6U36DAVEKECMKN5YEBQYZVRBPNSZAAKBCO6P5HBMDFSQMQL4Z4") + + account = history.AccountEntry{ + AccountID: accountID.Address(), + Balance: 20000, + SequenceNumber: 223456789, + NumSubEntries: 10, + InflationDestination: inflationDest.Address(), + Flags: 1, + HomeDomain: "stellar.org", + ThresholdLow: 1, + ThresholdMedium: 2, + ThresholdHigh: 3, + SellingLiabilities: 4, + BuyingLiabilities: 3, + LastModifiedLedger: 1000, + } + + trustLineIssuer = xdr.MustAddress("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H") + + trustLines = []history.TrustLine{ + history.TrustLine{ + AccountID: accountID.Address(), + AssetCode: "EUR", + AssetIssuer: trustLineIssuer.Address(), + AssetType: 1, + Balance: 20000, + Limit: 223456789, + Flags: 1, + SellingLiabilities: 3, + BuyingLiabilities: 4, + LastModifiedLedger: 900, + }, + history.TrustLine{ + AccountID: accountID.Address(), + AssetCode: "USD", + AssetIssuer: trustLineIssuer.Address(), + AssetType: 1, + Balance: 10000, + Limit: 123456789, + Flags: 0, + SellingLiabilities: 2, + BuyingLiabilities: 1, + LastModifiedLedger: 900, + }, + } + + signers = []history.AccountSigner{ + history.AccountSigner{ + Account: accountID.Address(), + Signer: accountID.Address(), + Weight: int32(3), + }, + + history.AccountSigner{ + Account: accountID.Address(), + Signer: "GCMQBJWOLTCSSMWNVDJAXL6E42SADH563IL5MN5B6RBBP4XP7TBRLJKE", + Weight: int32(1), + }, + history.AccountSigner{ + Account: accountID.Address(), + Signer: "GBXSGN5GX4PZOSBHB4JJF67CEGSGT56IN2N7LF3VGJ7WQ56BYWRVNNDX", + Weight: int32(2), + }, + history.AccountSigner{ + Account: accountID.Address(), + Signer: "GBPXUGDRAOU5QUNUAXX6LYPBIOXYG45GLTKIRWKOCQ6HXP5QE5OCPFBY", + Weight: int32(3), + }, + } +) + +func TestPopulateAccountEntry(t *testing.T) { + tt := assert.New(t) + ctx, _ := test.ContextWithLogBuffer() + hAccount := Account{} + err := PopulateAccountEntry(ctx, &hAccount, account, data, signers, trustLines) + tt.NoError(err) + + tt.Equal(account.AccountID, hAccount.ID) + tt.Equal(account.AccountID, hAccount.AccountID) + tt.Equal(account.AccountID, hAccount.PT) + tt.Equal(strconv.FormatInt(account.SequenceNumber, 10), hAccount.Sequence) + tt.Equal(int32(account.NumSubEntries), hAccount.SubentryCount) + tt.Equal(account.InflationDestination, hAccount.InflationDestination) + tt.Equal(account.HomeDomain, hAccount.HomeDomain) + tt.Equal(account.LastModifiedLedger, hAccount.LastModifiedLedger) + + wantAccountThresholds := AccountThresholds{ + LowThreshold: account.ThresholdLow, + MedThreshold: account.ThresholdMedium, + HighThreshold: account.ThresholdHigh, + } + tt.Equal(wantAccountThresholds, hAccount.Thresholds) + + wantFlags := AccountFlags{ + AuthRequired: account.IsAuthRequired(), + AuthRevocable: account.IsAuthRevocable(), + AuthImmutable: account.IsAuthImmutable(), + } + + tt.Equal(wantFlags, hAccount.Flags) + + for _, d := range data { + want, e := base64.StdEncoding.DecodeString(hAccount.Data[d.Name]) + tt.NoError(e) + tt.Equal(d.Value, history.AccountDataValue(want)) + } + + tt.Len(hAccount.Balances, 3) + + for i, t := range trustLines { + ht := hAccount.Balances[i] + tt.Equal(t.AssetIssuer, ht.Issuer) + tt.Equal(t.AssetCode, ht.Code) + wantType, e := assets.String(t.AssetType) + tt.NoError(e) + tt.Equal(wantType, ht.Type) + + tt.Equal(amount.StringFromInt64(t.Balance), ht.Balance) + tt.Equal(amount.StringFromInt64(t.BuyingLiabilities), ht.BuyingLiabilities) + tt.Equal(amount.StringFromInt64(t.SellingLiabilities), ht.SellingLiabilities) + tt.Equal(amount.StringFromInt64(t.Limit), ht.Limit) + tt.Equal(t.LastModifiedLedger, ht.LastModifiedLedger) + tt.Equal(t.IsAuthorized(), *ht.IsAuthorized) + } + + native := hAccount.Balances[len(hAccount.Balances)-1] + + tt.Equal("native", native.Type) + tt.Equal("0.0020000", native.Balance) + tt.Equal("0.0000003", native.BuyingLiabilities) + tt.Equal("0.0000004", native.SellingLiabilities) + tt.Equal("", native.Limit) + tt.Equal("", native.Issuer) + tt.Equal("", native.Code) + + tt.Len(hAccount.Signers, 4) + for i, s := range signers { + hs := hAccount.Signers[i] + tt.Equal(s.Signer, hs.Key) + tt.Equal(s.Weight, hs.Weight) + tt.Equal(protocol.MustKeyTypeFromAddress(s.Signer), hs.Type) + } + + links, err := json.Marshal(hAccount.Links) + want := ` + { + "data": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/data/{key}", + "templated": true + }, + "effects": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/effects{?cursor,limit,order}", + "templated": true + }, + "offers": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/offers{?cursor,limit,order}", + "templated": true + }, + "operations": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/operations{?cursor,limit,order}", + "templated": true + }, + "payments": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/payments{?cursor,limit,order}", + "templated": true + }, + "self": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB" + }, + "trades": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/trades{?cursor,limit,order}", + "templated": true + }, + "transactions": { + "href": "/accounts/GAOQJGUAB7NI7K7I62ORBXMN3J4SSWQUQ7FOEPSDJ322W2HMCNWPHXFB/transactions{?cursor,limit,order}", + "templated": true + } + } + ` + tt.JSONEq(want, string(links)) +} + +func TestPopulateAccountEntryMasterMissingInSigners(t *testing.T) { + tt := assert.New(t) + ctx, _ := test.ContextWithLogBuffer() + hAccount := Account{} + + account.MasterWeight = 0 + signers = []history.AccountSigner{ + history.AccountSigner{ + Account: accountID.Address(), + Signer: "GCMQBJWOLTCSSMWNVDJAXL6E42SADH563IL5MN5B6RBBP4XP7TBRLJKE", + Weight: int32(3), + }, + } + err := PopulateAccountEntry(ctx, &hAccount, account, data, signers, trustLines) + tt.NoError(err) + + tt.Len(hAccount.Signers, 2) + + signer := hAccount.Signers[1] + tt.Equal(account.AccountID, signer.Key) + tt.Equal(int32(account.MasterWeight), signer.Weight) + tt.Equal(protocol.MustKeyTypeFromAddress(account.AccountID), signer.Type) +} diff --git a/services/horizon/internal/resourceadapter/balance.go b/services/horizon/internal/resourceadapter/balance.go index 4e7eaa7084..b0fd3f2445 100644 --- a/services/horizon/internal/resourceadapter/balance.go +++ b/services/horizon/internal/resourceadapter/balance.go @@ -5,6 +5,7 @@ import ( protocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/services/horizon/internal/assets" "github.com/stellar/go/services/horizon/internal/db2/core" + "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) @@ -27,6 +28,24 @@ func PopulateBalance(dest *protocol.Balance, row core.Trustline) (err error) { return } +func PopulateHistoryBalance(dest *protocol.Balance, row history.TrustLine) (err error) { + dest.Type, err = assets.String(row.AssetType) + if err != nil { + return errors.Wrap(err, "getting the string representation from the provided xdr asset type") + } + + dest.Balance = amount.StringFromInt64(row.Balance) + dest.BuyingLiabilities = amount.StringFromInt64(row.BuyingLiabilities) + dest.SellingLiabilities = amount.StringFromInt64(row.SellingLiabilities) + dest.Limit = amount.StringFromInt64(row.Limit) + dest.Issuer = row.AssetIssuer + dest.Code = row.AssetCode + dest.LastModifiedLedger = row.LastModifiedLedger + isAuthorized := row.IsAuthorized() + dest.IsAuthorized = &isAuthorized + return +} + func PopulateNativeBalance(dest *protocol.Balance, stroops, buyingLiabilities, sellingLiabilities xdr.Int64) (err error) { dest.Type, err = assets.String(xdr.AssetTypeAssetTypeNative) if err != nil { diff --git a/services/horizon/internal/resourceadapter/balance_test.go b/services/horizon/internal/resourceadapter/balance_test.go index 11d61f3897..fbf013e99b 100644 --- a/services/horizon/internal/resourceadapter/balance_test.go +++ b/services/horizon/internal/resourceadapter/balance_test.go @@ -5,6 +5,7 @@ import ( . "github.com/stellar/go/protocols/horizon" "github.com/stellar/go/services/horizon/internal/db2/core" + "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/xdr" "github.com/stretchr/testify/assert" ) @@ -52,6 +53,49 @@ func TestPopulateBalance(t *testing.T) { assert.Equal(t, false, *want.IsAuthorized) } +func TestPopulateHistoryBalance(t *testing.T) { + testAssetCode1 := "TEST_ASSET_1" + testAssetCode2 := "TEST_ASSET_2" + authorizedTrustline := history.TrustLine{ + AccountID: "testID", + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum12, + AssetIssuer: "", + AssetCode: testAssetCode1, + Limit: 100, + Balance: 10, + Flags: 1, + } + unauthorizedTrustline := history.TrustLine{ + AccountID: "testID", + AssetType: xdr.AssetTypeAssetTypeCreditAlphanum12, + AssetIssuer: "", + AssetCode: testAssetCode2, + Limit: 100, + Balance: 10, + Flags: 2, + } + + want := Balance{} + err := PopulateHistoryBalance(&want, authorizedTrustline) + assert.NoError(t, err) + assert.Equal(t, "credit_alphanum12", want.Type) + assert.Equal(t, "0.0000010", want.Balance) + assert.Equal(t, "0.0000100", want.Limit) + assert.Equal(t, "", want.Issuer) + assert.Equal(t, testAssetCode1, want.Code) + assert.Equal(t, true, *want.IsAuthorized) + + want = Balance{} + err = PopulateHistoryBalance(&want, unauthorizedTrustline) + assert.NoError(t, err) + assert.Equal(t, "credit_alphanum12", want.Type) + assert.Equal(t, "0.0000010", want.Balance) + assert.Equal(t, "0.0000100", want.Limit) + assert.Equal(t, "", want.Issuer) + assert.Equal(t, testAssetCode2, want.Code) + assert.Equal(t, false, *want.IsAuthorized) +} + func TestPopulateNativeBalance(t *testing.T) { want := Balance{} err := PopulateNativeBalance(&want, 10, 10, 10) diff --git a/xdr/account_flags.go b/xdr/account_flags.go new file mode 100644 index 0000000000..6bb32c504a --- /dev/null +++ b/xdr/account_flags.go @@ -0,0 +1,19 @@ +package xdr + +// IsAuthRequired returns true if the account has the "AUTH_REQUIRED" option +// turned on. +func (accountFlags AccountFlags) IsAuthRequired() bool { + return (accountFlags & AccountFlagsAuthRequiredFlag) != 0 +} + +// IsAuthRevocable returns true if the account has the "AUTH_REVOCABLE" option +// turned on. +func (accountFlags AccountFlags) IsAuthRevocable() bool { + return (accountFlags & AccountFlagsAuthRevocableFlag) != 0 +} + +// IsAuthImmutable returns true if the account has the "AUTH_IMMUTABLE" option +// turned on. +func (accountFlags AccountFlags) IsAuthImmutable() bool { + return (accountFlags & AccountFlagsAuthImmutableFlag) != 0 +} diff --git a/xdr/account_flags_test.go b/xdr/account_flags_test.go new file mode 100644 index 0000000000..d73da5b747 --- /dev/null +++ b/xdr/account_flags_test.go @@ -0,0 +1,57 @@ +package xdr_test + +import ( + "testing" + + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" +) + +func TestIsAuthRequired(t *testing.T) { + tt := assert.New(t) + + flag := xdr.AccountFlags(1) + tt.True(flag.IsAuthRequired()) + + flag = xdr.AccountFlags(0) + tt.False(flag.IsAuthRequired()) + + flag = xdr.AccountFlags(2) + tt.False(flag.IsAuthRequired()) + + flag = xdr.AccountFlags(4) + tt.False(flag.IsAuthRequired()) + +} + +func TestIsAuthRevocable(t *testing.T) { + tt := assert.New(t) + + flag := xdr.AccountFlags(2) + tt.True(flag.IsAuthRevocable()) + + flag = xdr.AccountFlags(0) + tt.False(flag.IsAuthRevocable()) + + flag = xdr.AccountFlags(1) + tt.False(flag.IsAuthRevocable()) + + flag = xdr.AccountFlags(4) + tt.False(flag.IsAuthRevocable()) + +} +func TestIsAuthImmutable(t *testing.T) { + tt := assert.New(t) + + flag := xdr.AccountFlags(4) + tt.True(flag.IsAuthImmutable()) + + flag = xdr.AccountFlags(0) + tt.False(flag.IsAuthImmutable()) + + flag = xdr.AccountFlags(1) + tt.False(flag.IsAuthImmutable()) + + flag = xdr.AccountFlags(2) + tt.False(flag.IsAuthImmutable()) +} diff --git a/xdr/trust_line_flags.go b/xdr/trust_line_flags.go new file mode 100644 index 0000000000..bdae1fb266 --- /dev/null +++ b/xdr/trust_line_flags.go @@ -0,0 +1,7 @@ +package xdr + +// IsAuthorized returns true if issuer has authorized account to perform +// transactions with its credit +func (e TrustLineFlags) IsAuthorized() bool { + return (e & TrustLineFlagsAuthorizedFlag) != 0 +} diff --git a/xdr/trust_line_flags_test.go b/xdr/trust_line_flags_test.go new file mode 100644 index 0000000000..a50b5b21c3 --- /dev/null +++ b/xdr/trust_line_flags_test.go @@ -0,0 +1,21 @@ +package xdr_test + +import ( + "testing" + + "github.com/stellar/go/xdr" + "github.com/stretchr/testify/assert" +) + +func TestIsAuthorized(t *testing.T) { + tt := assert.New(t) + + flag := xdr.TrustLineFlags(1) + tt.True(flag.IsAuthorized()) + + flag = xdr.TrustLineFlags(0) + tt.False(flag.IsAuthorized()) + + flag = xdr.TrustLineFlags(2) + tt.False(flag.IsAuthorized()) +}