Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* use txnbuild

* use horizonclient error types

* fix checkFundAccount which returned an invalid hProtocol.Account structure

It was invalid because it was fetch before it existed and therefore was incomplete.

* use client registered on APIServer instead of using default horizonclient

* fix formatting of txnbuild.CreditAsset struct instantiations

* distinguish equality methods in utils

* panic if we cannot create a delete offer operation

avoids threading errors through in this situation where really there should be no reason for an error from the delete offer op, althrough ideally we should thread the error through

* remove TODO in sdex.go#submitOps and add messages around errors

* fix float64 vs. stoops value string in manageSellOffer.Amount

* update log line from build.ManageOfferBuilder -> txnbuild.ManageSellOffer

* add string price in error message when attempting conversion to float

* convert horizon.Asset -> hProtocol.Asset

* remove last references to horizon.Client

* remove build and clients/horizon package from glide yaml and lock file

* use build package in API interfaces + undo glide removals
  • Loading branch information
poliha authored and nikhilsaraf committed Sep 3, 2019
1 parent 6e0fc57 commit c18c97f
Show file tree
Hide file tree
Showing 21 changed files with 449 additions and 281 deletions.
84 changes: 84 additions & 0 deletions api/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package api

import (
"fmt"
"math"

"github.com/stellar/go/build"
hProtocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/txnbuild"
"github.com/stellar/go/xdr"
"github.com/stellar/kelp/model"
)

Expand Down Expand Up @@ -230,3 +233,84 @@ type ExchangeShim interface {
OrderbookFetcher
FillTrackable
}

// ConvertOperation2TM is a temporary adapter to support transitioning from the old Go SDK to the new SDK without having to bump the major version
func ConvertOperation2TM(ops []txnbuild.Operation) []build.TransactionMutator {
muts := []build.TransactionMutator{}
for _, o := range ops {
var mob build.ManageOfferBuilder
if mso, ok := o.(*txnbuild.ManageSellOffer); ok {
mob = build.ManageOffer(
false,
build.Amount(mso.Amount),
build.Rate{
Selling: build.Asset{Code: mso.Selling.GetCode(), Issuer: mso.Selling.GetIssuer(), Native: mso.Selling.IsNative()},
Buying: build.Asset{Code: mso.Buying.GetCode(), Issuer: mso.Buying.GetIssuer(), Native: mso.Buying.IsNative()},
Price: build.Price(mso.Price),
},
build.OfferID(mso.OfferID),
)
if mso.SourceAccount != nil {
mob.Mutate(build.SourceAccount{AddressOrSeed: mso.SourceAccount.GetAccountID()})
}
} else {
panic(fmt.Sprintf("could not convert txnbuild.Operation to build.TransactionMutator: %v\n", o))
}
muts = append(muts, mob)
}
return muts
}

// ConvertTM2Operation is a temporary adapter to support transitioning from the old Go SDK to the new SDK without having to bump the major version
func ConvertTM2Operation(muts []build.TransactionMutator) []txnbuild.Operation {
ops := []txnbuild.Operation{}
for _, m := range muts {
var mso *txnbuild.ManageSellOffer
if mob, ok := m.(build.ManageOfferBuilder); ok {
mso = convertMOB2MSO(mob)
} else if mob, ok := m.(*build.ManageOfferBuilder); ok {
mso = convertMOB2MSO(*mob)
} else {
panic(fmt.Sprintf("could not convert build.TransactionMutator to txnbuild.Operation: %v (type=%T)\n", m, m))
}
ops = append(ops, mso)
}
return ops
}

func convertMOB2MSO(mob build.ManageOfferBuilder) *txnbuild.ManageSellOffer {
mso := &txnbuild.ManageSellOffer{
Amount: fmt.Sprintf("%.7f", float64(mob.MO.Amount)/math.Pow(10, 7)),
OfferID: int64(mob.MO.OfferId),
Price: fmt.Sprintf("%.7f", float64(mob.MO.Price.N)/float64(mob.MO.Price.D)),
}
if mob.O.SourceAccount != nil {
mso.SourceAccount = &txnbuild.SimpleAccount{
AccountID: mob.O.SourceAccount.Address(),
}
}

if mob.MO.Buying.Type == xdr.AssetTypeAssetTypeNative {
mso.Buying = txnbuild.NativeAsset{}
} else {
var tipe, code, issuer string
mob.MO.Buying.MustExtract(&tipe, &code, &issuer)
mso.Buying = txnbuild.CreditAsset{
Code: code,
Issuer: issuer,
}
}

if mob.MO.Selling.Type == xdr.AssetTypeAssetTypeNative {
mso.Selling = txnbuild.NativeAsset{}
} else {
var tipe, code, issuer string
mob.MO.Selling.MustExtract(&tipe, &code, &issuer)
mso.Selling = txnbuild.CreditAsset{
Code: code,
Issuer: issuer,
}
}

return mso
}
7 changes: 3 additions & 4 deletions cmd/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (

"github.com/nikhilsaraf/go-tools/multithreading"
"github.com/spf13/cobra"
"github.com/stellar/go/build"
"github.com/stellar/go/clients/horizonclient"
hProtocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/support/config"
Expand Down Expand Up @@ -198,7 +197,7 @@ func makeExchangeShimSdex(
options inputs,
client *horizonclient.Client,
ieif *plugins.IEIF,
network build.Network,
network string,
threadTracker *multithreading.ThreadTracker,
tradingPair *model.TradingPair,
) (api.ExchangeShim, *plugins.SDEX) {
Expand Down Expand Up @@ -290,7 +289,7 @@ func makeExchangeShimSdex(

func makeStrategy(
l logger.Logger,
network build.Network,
network string,
botConfig trader.BotConfig,
client *horizonclient.Client,
sdex *plugins.SDEX,
Expand Down Expand Up @@ -698,7 +697,7 @@ func deleteAllOffersAndExit(
l.Infof("created %d operations to delete offers\n", len(dOps))

if len(dOps) > 0 {
e := exchangeShim.SubmitOpsSynch(dOps, func(hash string, e error) {
e := exchangeShim.SubmitOpsSynch(api.ConvertOperation2TM(dOps), func(hash string, e error) {
if e != nil {
logger.Fatal(l, e)
return
Expand Down
6 changes: 2 additions & 4 deletions glide.lock

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

1 change: 0 additions & 1 deletion glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import:
version: a599ed95b928a7bdcee21cee4999efd05e43c2df
subpackages:
- build
- clients/horizon
- clients/horizonclient
- support/config
- support/errors
Expand Down
13 changes: 0 additions & 13 deletions gui/backend/api_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"path/filepath"
"strings"

"github.com/stellar/go/clients/horizon"
"github.com/stellar/go/clients/horizonclient"
"github.com/stellar/kelp/support/kelpos"
)
Expand All @@ -27,8 +26,6 @@ type APIServer struct {
ccxtRestUrl string
apiTestNet *horizonclient.Client
apiPubNet *horizonclient.Client
apiTestNetOld *horizon.Client
apiPubNetOld *horizon.Client
cachedOptionsMetadata metadata
}

Expand Down Expand Up @@ -56,14 +53,6 @@ func MakeAPIServer(kos *kelpos.KelpOS, horizonTestnetURI string, horizonPubnetUR
HorizonURL: horizonPubnetURI,
HTTP: http.DefaultClient,
}
apiTestNetOld := &horizon.Client{
URL: horizonTestnetURI,
HTTP: http.DefaultClient,
}
apiPubNetOld := &horizon.Client{
URL: horizonPubnetURI,
HTTP: http.DefaultClient,
}

optionsMetadata, e := loadOptionsMetadata()
if e != nil {
Expand All @@ -81,8 +70,6 @@ func MakeAPIServer(kos *kelpos.KelpOS, horizonTestnetURI string, horizonPubnetUR
ccxtRestUrl: ccxtRestUrl,
apiTestNet: apiTestNet,
apiPubNet: apiPubNet,
apiTestNetOld: apiTestNetOld,
apiPubNetOld: apiPubNetOld,
cachedOptionsMetadata: optionsMetadata,
}, nil
}
Expand Down
79 changes: 60 additions & 19 deletions gui/backend/autogenerate_bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import (
"log"
"net/http"

"github.com/stellar/go/build"
"github.com/stellar/go/clients/horizonclient"
"github.com/stellar/go/keypair"
"github.com/stellar/go/network"
hProtocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/txnbuild"
"github.com/stellar/kelp/gui/model2"
"github.com/stellar/kelp/plugins"
"github.com/stellar/kelp/support/kelpos"
Expand Down Expand Up @@ -97,38 +98,62 @@ func (s *APIServer) autogenerateBot(w http.ResponseWriter, r *http.Request) {
}

func (s *APIServer) setupAccount(address string, signer string, botName string) error {
_, e := s.checkFundAccount(address, botName)
fundedAccount, e := s.checkFundAccount(address, botName)
if e != nil {
return fmt.Errorf("error checking and funding account: %s\n", e)
}

client := s.apiTestNetOld
txn, e := build.Transaction(
build.SourceAccount{AddressOrSeed: address},
build.AutoSequence{SequenceProvider: client},
build.TestNetwork,
build.Trust("COUPON", "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI"),
build.Payment(
build.Destination{AddressOrSeed: address},
build.CreditAmount{Code: "COUPON", Issuer: "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI", Amount: "1000.0"},
build.SourceAccount{AddressOrSeed: "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI"},
),
)
var txOps []txnbuild.Operation
trustOp := txnbuild.ChangeTrust{
Line: txnbuild.CreditAsset{
Code: "COUPON",
Issuer: "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI",
},
}
txOps = append(txOps, &trustOp)

paymentOp := txnbuild.Payment{
Destination: address,
Amount: "1000.0",
Asset: txnbuild.CreditAsset{
Code: "COUPON",
Issuer: "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI",
},
SourceAccount: &txnbuild.SimpleAccount{AccountID: "GBMMZMK2DC4FFP4CAI6KCVNCQ7WLO5A7DQU7EC7WGHRDQBZB763X4OQI"},
}
txOps = append(txOps, &paymentOp)

tx := txnbuild.Transaction{
SourceAccount: fundedAccount,
Operations: txOps,
Timebounds: txnbuild.NewInfiniteTimeout(),
Network: network.TestNetworkPassphrase,
BaseFee: 100,
}
e = tx.Build()
if e != nil {
return fmt.Errorf("cannot create trustline transaction for account %s for bot '%s': %s\n", address, botName, e)
}

txnS, e := txn.Sign(signer, issuerSeed)
if e != nil {
return fmt.Errorf("cannot sign trustline transaction for account %s for bot '%s': %s\n", address, botName, e)
for _, s := range []string{signer, issuerSeed} {
kp, e := keypair.Parse(s)
if e != nil {
return fmt.Errorf("cannot parse seed %s required for signing: %s\n", s, e)
}

e = tx.Sign(kp.(*keypair.Full))
if e != nil {
return fmt.Errorf("cannot sign trustline transaction for account %s for bot '%s': %s\n", address, botName, e)
}
}

txn64, e := txnS.Base64()
txn64, e := tx.Base64()
if e != nil {
return fmt.Errorf("cannot convert trustline transaction to base64 for account %s for bot '%s': %s\n", address, botName, e)
}

resp, e := client.SubmitTransaction(txn64)
client := s.apiTestNet
resp, e := client.SubmitTransactionXDR(txn64)
if e != nil {
return fmt.Errorf("error submitting change trust transaction for address %s for bot '%s': %s\n", address, botName, e)
}
Expand Down Expand Up @@ -165,6 +190,22 @@ func (s *APIServer) checkFundAccount(address string, botName string) (*hProtocol
return nil, fmt.Errorf("error funding address %s for bot '%s': %s\n", address, botName, e)
}
log.Printf("successfully funded account %s for bot '%s': %s\n", address, botName, fundResponse)

// refetch account to confirm
account, e = s.apiTestNet.AccountDetail(horizonclient.AccountRequest{AccountID: address})
if e != nil {
var herr *horizonclient.Error
switch t := e.(type) {
case *horizonclient.Error:
herr = t
case horizonclient.Error:
herr = &t
default:
return nil, fmt.Errorf("unexpected error when checking for existence of account %s for bot '%s': %s", address, botName, e)
}

return nil, fmt.Errorf("horizon error when checking for existence of account %s for bot '%s': %d (%v) -- could this be caused because horizon has not ingested this data yet? (programmer: maybe create hProtocol.Account instance manually instead of fetching)", address, botName, herr.Problem.Status, *herr)
}
return &account, nil
}

Expand Down
3 changes: 1 addition & 2 deletions gui/backend/get_bot_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strings"
"time"

"github.com/stellar/go/clients/horizon"
"github.com/stellar/go/clients/horizonclient"
hProtocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/support/config"
Expand Down Expand Up @@ -215,7 +214,7 @@ func getNativeBalance(account hProtocol.Account) (float64, error) {
return balance, nil
}

func getCreditBalance(account hProtocol.Account, asset horizon.Asset) (float64, error) {
func getCreditBalance(account hProtocol.Account, asset hProtocol.Asset) (float64, error) {
balanceString := account.GetCreditBalance(asset.Code, asset.Issuer)
balance, e := strconv.ParseFloat(balanceString, 64)
if e != nil {
Expand Down
Loading

0 comments on commit c18c97f

Please sign in to comment.