func TestMicroStellarOrderBook(t *testing.T) {
	const fundSourceSeed = "SBW2N5EK5MZTKPQJZ6UYXEMCA63AO3AVUR6U5CUOIDFYCAR2X2IJIZAX"
	ms := microstellar.New("test")
	issuer := createFundedAccount(ms, fundSourceSeed, true)
	bob := createFundedAccount(ms, issuer.Seed, false)
	log.Print("Pair1 (issuer): ", issuer)
	log.Print("Pair2 (bob): ", bob)
	debugf("Creating new USD asset issued by %s (issuer)...", issuer.Address)
	USD := microstellar.NewAsset("USD", issuer.Address, microstellar.Credit4Type)
	debugf("Setting AUTH_REQUIRED on issuer...")
	err := ms.SetFlags(issuer.Seed, microstellar.FlagAuthRequired)
	if err != nil {
		log.Fatalf("SetFlags: %+v", err)
	}
	debugf("Creating USD trustline for %s (bob)...", bob.Address)
	err = ms.CreateTrustLine(bob.Seed, USD, "1000000")
	if err != nil {
		log.Fatalf("CreateTrustLine: %+v", err)
	}
	debugf("Authorizing trustline to bob...")
	err = ms.AllowTrust(issuer.Seed, bob.Address, "USD", true)
	if err != nil {
		log.Fatalf("AllowTrust: %v", microstellar.ErrorString(err))
	}
	log.Print("Issuing USD to bob...")
	err = ms.Pay(issuer.Seed, bob.Address, "500000", USD)
	if err != nil {
		log.Fatalf("Pay: %+v", microstellar.ErrorString(err))
	}
	log.Print("Creating offer for Bob to sell 100 USD...")
	err = ms.CreateOffer(bob.Seed, USD, microstellar.NativeAsset, "2", "50")
	if err != nil {
		log.Fatalf("CreateOffer: %+v", microstellar.ErrorString(err))
	}
	orderBook, err := ms.LoadOrderBook(USD, microstellar.NativeAsset)
	if err != nil {
		log.Fatalf("LoadOrderBook: %+v", err)
	}
	orderBookJSON, _ := json.MarshalIndent(*orderBook, "", "  ")
	log.Printf("%v", string(orderBookJSON))
	if len(orderBook.Asks) != 1 {
		t.Errorf("Expecting 1 ask, got %v", len(orderBook.Asks))
	}
	orderBook, err = ms.LoadOrderBook(USD, microstellar.NativeAsset, microstellar.Opts().WithLimit(0))
	if err != nil {
		log.Fatalf("LoadOrderBook: %+v", err)
	}
	orderBookJSON, _ = json.MarshalIndent(*orderBook, "", "  ")
	log.Printf("%v", string(orderBookJSON))
	if len(orderBook.Asks) != 0 {
		t.Errorf("Expecting 0 asks, got %v", len(orderBook.Asks))
	}
}
TestMicroStellarOffers implement end-to-end DEX tests
package macrotest
import (
	"encoding/json"
	"fmt"
	"log"
	"testing"
	"github.com/0xfe/microstellar"
)
func showOffersAndBalances(ms *microstellar.MicroStellar, asset *microstellar.Asset, name, address string) {
	showBalance(ms, asset, name, address)
	offers, err := ms.LoadOffers(address)
	if err != nil {
		log.Fatalf("LoadOffers: %+v", microstellar.ErrorString(err))
	}
	debugf("Offers by %s: %d avaialable", name, len(offers))
	for i, o := range offers {
		offerJSON, err := json.MarshalIndent(o, "", "  ")
		if err != nil {
			log.Fatalf("MarshalIndent: %v", err)
		}
		debugf("Offer %d:\n%s", i, string(offerJSON))
	}
}
func TestMicroStellarOffers(t *testing.T) {
	const fundSourceSeed = "SBW2N5EK5MZTKPQJZ6UYXEMCA63AO3AVUR6U5CUOIDFYCAR2X2IJIZAX"
	ms := microstellar.New("test")
	issuer := createFundedAccount(ms, fundSourceSeed, true)
	bob := createFundedAccount(ms, issuer.Seed, false)
	mary := createFundedAccount(ms, issuer.Seed, false)
	log.Print("Pair1 (issuer): ", issuer)
	log.Print("Pair2 (bob): ", bob)
	log.Print("Pair3 (mary): ", mary)
	debugf("Creating new USD asset issued by %s (issuer)...", issuer.Address)
	USD := microstellar.NewAsset("USD", issuer.Address, microstellar.Credit4Type)
	debugf("Creating USD trustline for %s (bob)...", bob.Address)
	err := ms.CreateTrustLine(bob.Seed, USD, "1000000")
	if err != nil {
		log.Fatalf("CreateTrustLine: %+v", err)
	}
	debugf("Creating USD trustline for %s (mary)...", mary.Address)
	err = ms.CreateTrustLine(mary.Seed, USD, "1000000")
	if err != nil {
		log.Fatalf("CreateTrustLine: %+v", err)
	}
	log.Print("Issuing USD to bob...")
	err = ms.Pay(issuer.Seed, bob.Address, "500000", USD)
	if err != nil {
		log.Fatalf("Pay: %+v", microstellar.ErrorString(err))
	}
	log.Print("Issuing USD to mary...")
	err = ms.Pay(issuer.Seed, mary.Address, "500000", USD)
	if err != nil {
		log.Fatalf("Pay: %+v", microstellar.ErrorString(err))
	}
	showBalance(ms, USD, "bob", bob.Address)
	showBalance(ms, USD, "mary", mary.Address)
	log.Print("Creating offer for Bob to sell 100 USD...")
	err = ms.CreateOffer(bob.Seed, USD, microstellar.NativeAsset, "2", "50")
	if err != nil {
		log.Fatalf("CreateOffer: %+v", microstellar.ErrorString(err))
	}
	showOffersAndBalances(ms, USD, "bob", bob.Address)
	debugf("Creating offer for Mary to buy Bob's assets...")
	err = ms.CreateOffer(mary.Seed, microstellar.NativeAsset, USD, "0.5", "100")
	if err != nil {
		log.Fatalf("CreateOffer: %+v", microstellar.ErrorString(err))
	}
	debugf("Expecting 0 offers for Mary and Bob...")
	showOffersAndBalances(ms, USD, "bob", bob.Address)
	showOffersAndBalances(ms, USD, "mary", mary.Address)
	debugf("Creating another offer from Mary to sell XLM...")
	err = ms.CreateOffer(mary.Seed, microstellar.NativeAsset, USD, "0.5", "20")
	if err != nil {
		log.Fatalf("CreateOffer: %+v", microstellar.ErrorString(err))
	}
	offers, err := ms.LoadOffers(mary.Address)
	if err != nil {
		log.Fatalf("LoadOffers: %+v", microstellar.ErrorString(err))
	}
	if len(offers) != 1 {
		log.Fatalf("wrong number of offers, want %v, got %v", 1, len(offers))
	}
	debugf("Updating mary's offer...")
	offerID := fmt.Sprintf("%d", offers[0].ID)
	err = ms.UpdateOffer(mary.Seed, offerID, microstellar.NativeAsset, USD, "0.5", "5")
	if err != nil {
		log.Fatalf("UpdateOffer: %+v", microstellar.ErrorString(err))
	}
	offers, err = ms.LoadOffers(mary.Address)
	if err != nil {
		log.Fatalf("LoadOffers: %+v", microstellar.ErrorString(err))
	}
	if offers[0].Amount != "5.0000000" {
		showOffersAndBalances(ms, USD, "mary", mary.Address)
		log.Fatalf("wrong amount, want %v, got %v", "5.0000000", offers[0].Amount)
	}
	debugf("Deleting mary's offer...")
	err = ms.DeleteOffer(mary.Seed, offerID, microstellar.NativeAsset, USD, "0.5")
	if err != nil {
		log.Fatalf("DeleteOffer: %+v", microstellar.ErrorString(err))
	}
	offers, err = ms.LoadOffers(mary.Address)
	if err != nil {
		log.Fatalf("LoadOffers: %+v", microstellar.ErrorString(err))
	}
	if len(offers) != 0 {
		showOffersAndBalances(ms, USD, "mary", mary.Address)
		log.Fatalf("wrong number of offers, want %v, got %v", 0, len(offers))
	}
}
func TestMicroStellarPathPayments(t *testing.T) {
	const fundSourceSeed = "SBW2N5EK5MZTKPQJZ6UYXEMCA63AO3AVUR6U5CUOIDFYCAR2X2IJIZAX"
	ms := microstellar.New("test")
	issuer := createFundedAccount(ms, fundSourceSeed, true)
	bob := createFundedAccount(ms, issuer.Seed, false)
	mary := createFundedAccount(ms, issuer.Seed, false)
	usdHolder := createFundedAccount(ms, issuer.Seed, false)
	eurHolder := createFundedAccount(ms, issuer.Seed, false)
	inrHolder := createFundedAccount(ms, issuer.Seed, false)
	log.Print("Pair1 (issuer): ", issuer)
	log.Print("Pair2 (bob): ", bob)
	log.Print("Pair3 (mary): ", mary)
	log.Print("Pair4 (usdHolder): ", usdHolder)
	log.Print("Pair5 (eurHolder): ", eurHolder)
	log.Print("Pair6 (inrHolder): ", inrHolder)
	debugf("Creating new USD, EUR, and INR assets issued by %s (issuer)...", issuer.Address)
	XLM := microstellar.NativeAsset
	USD := microstellar.NewAsset("USD", issuer.Address, microstellar.Credit4Type)
	EUR := microstellar.NewAsset("EUR", issuer.Address, microstellar.Credit4Type)
	INR := microstellar.NewAsset("INR", issuer.Address, microstellar.Credit4Type)
	debugf("Creating USD, EUR, and INR trustlines for everyone...")
	for i, k := range []microstellar.KeyPair{bob, mary, usdHolder, eurHolder, inrHolder} {
		debugf("Keypair %d USD", i+1)
		failOnError0("CreateTrustLine", ms.CreateTrustLine(k.Seed, USD, "1000000"))
		failOnError0("Pay (issue)", ms.Pay(issuer.Seed, k.Address, "500000", USD))
		debugf("Keypair %d EUR", i+1)
		failOnError0("CreateTrustLine", ms.CreateTrustLine(k.Seed, EUR, "1000000"))
		failOnError0("Pay (issue)", ms.Pay(issuer.Seed, k.Address, "500000", EUR))
		debugf("Keypair %d INR", i+1)
		failOnError0("CreateTrustLine", ms.CreateTrustLine(k.Seed, INR, "1000000"))
		failOnError0("Pay (issue)", ms.Pay(issuer.Seed, k.Address, "500000", INR))
	}
	debugf("Creating offers on the DEX...")
	failOnError0("CreateOffer (usdHolder)", ms.CreateOffer(usdHolder.Seed, USD, XLM, "1", "20"))
	failOnError0("CreateOffer (eurHolder)", ms.CreateOffer(eurHolder.Seed, EUR, USD, "1", "20"))
	failOnError0("CreateOffer (inrHolder)", ms.CreateOffer(inrHolder.Seed, INR, EUR, "1", "20"))
	showOffersAndBalances(ms, USD, "usdHolder", usdHolder.Address)
	showOffersAndBalances(ms, EUR, "eurHolder", eurHolder.Address)
	showOffersAndBalances(ms, INR, "inrHolder", inrHolder.Address)
	debugf("Before path payment...")
	showBalance(ms, INR, "bob", bob.Address)
	showBalance(ms, INR, "mary", mary.Address)
	paths, err := ms.FindPaths(bob.Address, mary.Address, INR, "5", microstellar.Opts().WithAsset(XLM, "5"))
	if err != nil {
		log.Fatalf("FindPaths: %+v", err)
	}
	debugf("FindPaths: found %d paths.", len(paths))
	debugf("Executing path payment...")
	err = ms.Pay(bob.Seed, mary.Address, "5", INR,
		microstellar.Opts().WithAsset(XLM, "10").Through(USD, EUR))
	if err != nil {
		log.Fatalf("Pay: %v", microstellar.ErrorString(err))
	}
	debugf("After path payment...")
	showBalance(ms, INR, "bob", bob.Address)
	showBalance(ms, INR, "mary", mary.Address)
	paths, err = ms.FindPaths(bob.Address, mary.Address, INR, "5", microstellar.Opts().WithAsset(XLM, "5"))
	if err != nil {
		log.Fatalf("FindPaths: %+v", err)
	}
	debugf("FindPaths: found %d paths.", len(paths))
	debugf("Executing path payment with pathfinder...")
	err = ms.Pay(bob.Seed, mary.Address, "5", INR,
		microstellar.Opts().WithAsset(XLM, "10").FindPathFrom(bob.Address))
	if err != nil {
		log.Fatalf("Pay: %v", microstellar.ErrorString(err))
	}
	debugf("After automatic path payment...")
	showBalance(ms, INR, "bob", bob.Address)
	showBalance(ms, INR, "mary", mary.Address)
}