Skip to content

Commit

Permalink
Merge pull request #81 from stellar/bifrost
Browse files Browse the repository at this point in the history
Bifrost - alpha version
  • Loading branch information
bartekn authored Dec 5, 2017
2 parents 76d9f4b + 14553a4 commit da7a365
Show file tree
Hide file tree
Showing 52 changed files with 4,337 additions and 9 deletions.
38 changes: 34 additions & 4 deletions clients/horizon/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"strconv"
"strings"

"github.com/stellar/go/support/errors"
"github.com/stellar/go/xdr"
Expand All @@ -24,9 +25,28 @@ func (c *Client) HomeDomainForAccount(aid string) (string, error) {
return a.HomeDomain, nil
}

// fixURL removes trailing slash from Client.URL. This will prevent situation when
// http.Client does not follow redirects.
func (c *Client) fixURL() {
c.URL = strings.TrimRight(c.URL, "/")
}

// Root loads the root endpoint of horizon
func (c *Client) Root() (root Root, err error) {
c.fixURLOnce.Do(c.fixURL)
resp, err := c.HTTP.Get(c.URL)
if err != nil {
return
}

err = decodeResponse(resp, &root)
return
}

// LoadAccount loads the account state from horizon. err can be either error
// object or horizon.Error object.
func (c *Client) LoadAccount(accountID string) (account Account, err error) {
c.fixURLOnce.Do(c.fixURL)
resp, err := c.HTTP.Get(c.URL + "/accounts/" + accountID)
if err != nil {
return
Expand All @@ -39,7 +59,7 @@ func (c *Client) LoadAccount(accountID string) (account Account, err error) {
// LoadAccountOffers loads the account offers from horizon. err can be either
// error object or horizon.Error object.
func (c *Client) LoadAccountOffers(accountID string, params ...interface{}) (offers OffersPage, err error) {

c.fixURLOnce.Do(c.fixURL)
endpoint := ""
query := url.Values{}

Expand Down Expand Up @@ -115,6 +135,7 @@ func (c *Client) SequenceForAccount(

// LoadOrderBook loads order book for given selling and buying assets.
func (c *Client) LoadOrderBook(selling Asset, buying Asset, params ...interface{}) (orderBook OrderBookSummary, err error) {
c.fixURLOnce.Do(c.fixURL)
query := url.Values{}

query.Add("selling_asset_type", selling.Type)
Expand Down Expand Up @@ -237,6 +258,7 @@ func (c *Client) stream(ctx context.Context, baseURL string, cursor *Cursor, han
// StreamLedgers streams incoming ledgers. Use context.WithCancel to stop streaming or
// context.Background() if you want to stream indefinitely.
func (c *Client) StreamLedgers(ctx context.Context, cursor *Cursor, handler LedgerHandler) (err error) {
c.fixURLOnce.Do(c.fixURL)
url := fmt.Sprintf("%s/ledgers", c.URL)
return c.stream(ctx, url, cursor, func(data []byte) error {
var ledger Ledger
Expand All @@ -252,6 +274,7 @@ func (c *Client) StreamLedgers(ctx context.Context, cursor *Cursor, handler Ledg
// StreamPayments streams incoming payments. Use context.WithCancel to stop streaming or
// context.Background() if you want to stream indefinitely.
func (c *Client) StreamPayments(ctx context.Context, accountID string, cursor *Cursor, handler PaymentHandler) (err error) {
c.fixURLOnce.Do(c.fixURL)
url := fmt.Sprintf("%s/accounts/%s/payments", c.URL, accountID)
return c.stream(ctx, url, cursor, func(data []byte) error {
var payment Payment
Expand All @@ -267,6 +290,7 @@ func (c *Client) StreamPayments(ctx context.Context, accountID string, cursor *C
// StreamTransactions streams incoming transactions. Use context.WithCancel to stop streaming or
// context.Background() if you want to stream indefinitely.
func (c *Client) StreamTransactions(ctx context.Context, accountID string, cursor *Cursor, handler TransactionHandler) (err error) {
c.fixURLOnce.Do(c.fixURL)
url := fmt.Sprintf("%s/accounts/%s/transactions", c.URL, accountID)
return c.stream(ctx, url, cursor, func(data []byte) error {
var transaction Transaction
Expand All @@ -280,9 +304,8 @@ func (c *Client) StreamTransactions(ctx context.Context, accountID string, curso
}

// SubmitTransaction submits a transaction to the network. err can be either error object or horizon.Error object.
func (c *Client) SubmitTransaction(
transactionEnvelopeXdr string,
) (response TransactionSuccess, err error) {
func (c *Client) SubmitTransaction(transactionEnvelopeXdr string) (response TransactionSuccess, err error) {
c.fixURLOnce.Do(c.fixURL)
v := url.Values{}
v.Set("tx", transactionEnvelopeXdr)

Expand All @@ -297,5 +320,12 @@ func (c *Client) SubmitTransaction(
return
}

// WARNING! Do not remove this code. If you include two trailing slashes (`//`) at the end of Client.URL
// and developers changed Client.HTTP to not follow redirects, this will return empty response and no error!
if resp.StatusCode != http.StatusOK {
err = errors.New("Invalid response code")
return
}

return
}
4 changes: 4 additions & 0 deletions clients/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package horizon
import (
"net/http"
"net/url"
"sync"

"github.com/stellar/go/build"
"github.com/stellar/go/support/errors"
Expand Down Expand Up @@ -64,9 +65,12 @@ type Client struct {

// HTTP client to make requests with
HTTP HTTP

fixURLOnce sync.Once
}

type ClientInterface interface {
Root() (Root, error)
LoadAccount(accountID string) (Account, error)
LoadAccountOffers(accountID string, params ...interface{}) (offers OffersPage, err error)
LoadMemo(p *Payment) error
Expand Down
6 changes: 6 additions & 0 deletions clients/horizon/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ type MockClient struct {
mock.Mock
}

// Root is a mocking a method
func (m *MockClient) Root() (Root, error) {
a := m.Called()
return a.Get(0).(Root), a.Error(1)
}

// LoadAccount is a mocking a method
func (m *MockClient) LoadAccount(accountID string) (Account, error) {
a := m.Called(accountID)
Expand Down
36 changes: 36 additions & 0 deletions clients/horizon/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ type Problem struct {
Extras map[string]json.RawMessage `json:"extras,omitempty"`
}

type Root struct {
Links struct {
Account Link `json:"account"`
AccountTransactions Link `json:"account_transactions"`
Friendbot Link `json:"friendbot"`
Metrics Link `json:"metrics"`
OrderBook Link `json:"order_book"`
Self Link `json:"self"`
Transaction Link `json:"transaction"`
Transactions Link `json:"transactions"`
} `json:"_links"`

HorizonVersion string `json:"horizon_version"`
StellarCoreVersion string `json:"core_version"`
HorizonSequence int32 `json:"history_latest_ledger"`
HistoryElderSequence int32 `json:"history_elder_ledger"`
CoreSequence int32 `json:"core_latest_ledger"`
CoreElderSequence int32 `json:"core_elder_ledger"`
NetworkPassphrase string `json:"network_passphrase"`
ProtocolVersion int32 `json:"protocol_version"`
}

type Account struct {
Links struct {
Self Link `json:"self"`
Expand Down Expand Up @@ -47,6 +69,16 @@ func (a Account) GetNativeBalance() string {
return "0"
}

func (a Account) GetCreditBalance(code, issuer string) string {
for _, balance := range a.Balances {
if balance.Asset.Code == code && balance.Asset.Issuer == issuer {
return balance.Balance
}
}

return "0"
}

// MustGetData returns decoded value for a given key. If the key does
// not exist, empty slice will be returned. If there is an error
// decoding a value, it will panic.
Expand Down Expand Up @@ -192,6 +224,10 @@ type Payment struct {
} `json:"transaction"`
} `json:"_links"`

// create_account fields
Account string `json:"account"`
StartingBalance string `json:"starting_balance"`

// payment/path_payment fields
From string `json:"from"`
To string `json:"to"`
Expand Down
82 changes: 77 additions & 5 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,15 @@ import:
- package: gopkg.in/yaml.v2
version: 7ad95dd0798a40da1ccdff6dff35fd177b5edf40
repo: https://gopkg.in/yaml.v2
- package: github.com/go-chi/chi
version: ~3.1.5
- package: github.com/tyler-smith/go-bip32
- package: github.com/btcsuite/btcd
subpackages:
- rpcclient
- package: github.com/btcsuite/btclog
- package: github.com/btcsuite/btcutil
- package: github.com/btcsuite/go-socks
subpackages:
- socks
- package: github.com/btcsuite/websocket
Loading

0 comments on commit da7a365

Please sign in to comment.