Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Use txnbuild #205

Merged
merged 16 commits into from
Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
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