Created
June 24, 2018 23:47
-
-
Save esomore/e12b89086990f0ea13031caf49565a79 to your computer and use it in GitHub Desktop.
bifrost stellar setup-script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"strconv" | |
"time" | |
"github.com/pkg/errors" | |
. "github.com/stellar/go/build" | |
"github.com/stellar/go/clients/horizon" | |
"github.com/stellar/go/keypair" | |
"github.com/tyler-smith/go-bip32" | |
) | |
const myToken = "TOKEN" | |
const newAccounts = true | |
func main() { | |
horizon.DefaultTestNetClient.HTTP = &http.Client{Timeout: 20 * time.Second} | |
var issuer, distributor *keypair.Full | |
if newAccounts { | |
log.Println("New test accounts") | |
issuer = createKeyPair() | |
distributor = createKeyPair() | |
log.Println("Fund the test accounts") | |
requestTestCredits(issuer.Address()) | |
requestTestCredits(distributor.Address()) | |
} else { | |
log.Println("Load the test accounts") | |
x := keypair.MustParse("SBRXXXXXXX") | |
issuer = x.(*keypair.Full) | |
log.Println("Issuer public key:" + issuer.Address()) | |
y := keypair.MustParse("SADXXXXXXXXX") | |
distributor = y.(*keypair.Full) | |
log.Println("Distributor public key:" + distributor.Address()) | |
} | |
log.Println("Await funding") | |
awaitTestBalance(issuer.Address()) | |
awaitTestBalance(distributor.Address()) | |
log.Println("Trust the issuing account") | |
autoSeq := AutoSequence{horizon.DefaultTestNetClient} | |
tx, err := Transaction( | |
SourceAccount{distributor.Address()}, | |
autoSeq, | |
TestNetwork, | |
Trust(myToken, issuer.Address(), Limit("10")), | |
) | |
if err != nil { | |
log.Fatal(err) | |
} | |
err = submitTransaction( | |
tx, | |
distributor) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("Create tokens") | |
tx, err = Transaction( | |
SourceAccount{issuer.Address()}, | |
autoSeq, | |
TestNetwork, | |
Payment( | |
Destination{distributor.Address()}, | |
CreditAmount{ | |
Code: myToken, | |
Issuer: issuer.Address(), | |
Amount: "10", | |
}, | |
), | |
) | |
if err != nil { | |
log.Fatal(err) | |
} | |
err = submitTransaction( | |
tx, | |
issuer) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("Create passive offer") | |
tx, err = Transaction( | |
SourceAccount{distributor.Address()}, | |
autoSeq, | |
TestNetwork, | |
CreatePassiveOffer(Rate{ | |
Selling: CreditAsset(myToken, issuer.Address()), | |
Buying: CreditAsset("ETH", distributor.Address()), | |
Price: Price("1"), | |
}, "10"), | |
) | |
if err != nil { | |
log.Fatal(err) | |
} | |
err = submitTransaction( | |
tx, distributor) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Generate a seed to determine all keys from. | |
// This should be persisted, backed up, and secured | |
seed, err := bip32.NewSeed() | |
if err != nil { | |
log.Fatalln("Error generating seed:", err) | |
} | |
privKey, err := bip44Key(seed) | |
if err != nil { | |
log.Fatalln("Error generating keys:", err) | |
} | |
// see: online generator: https://iancoleman.io/bip39/#english | |
log.Println("BIP32 address for ETH/BTC:") | |
log.Printf("master-private-seed: %X\n", seed) | |
log.Printf("master-private-key: %x\n", privKey.Key) | |
log.Printf("master-public: %s\n", privKey.PublicKey().String()) | |
for i := 0; i < 10; i++ { | |
child1, err := privKey.NewChildKey(uint32(i)) | |
if err != nil { | |
panic(err) | |
} | |
log.Printf("child-private-%d: %x\n", i, child1.Key) | |
} | |
} | |
func bip44Key(seed []byte) (*bip32.Key, error) { | |
// Create master private key from seed | |
// for existing keys you want to use bip32.B58Deserialize(rootKey) | |
privKey, err := bip32.NewMasterKey(seed) | |
if err != nil { | |
return nil, err | |
} | |
privKey, err = privKey.NewChildKey(44 + bip32.FirstHardenedChild) | |
if err != nil { | |
return nil, err | |
} | |
privKey, err = privKey.NewChildKey(60 + bip32.FirstHardenedChild) | |
if err != nil { | |
return nil, err | |
} | |
privKey, err = privKey.NewChildKey(0 + bip32.FirstHardenedChild) | |
if err != nil { | |
return nil, err | |
} | |
privKey, err = privKey.NewChildKey(0) | |
if err != nil { | |
return nil, err | |
} | |
return privKey, nil | |
} | |
func submitTransaction(tx *TransactionBuilder, signer *keypair.Full) error { | |
signedTX, err := tx.Sign(signer.Seed()) | |
if err != nil { | |
return err | |
} | |
signedTx, err := signedTX.Base64() | |
if err != nil { | |
return err | |
} | |
if _, err = horizon.DefaultTestNetClient.SubmitTransaction(signedTx); err != nil { | |
x, ok := err.(*horizon.Error) | |
if !ok { | |
return err | |
} | |
msg := "" | |
for k, v := range x.Problem.Extras { | |
msg += fmt.Sprintf("%s:%s", k, v) | |
} | |
return errors.New(msg) | |
} | |
return nil | |
} | |
func createKeyPair() *keypair.Full { | |
pair, err := keypair.Random() | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("private key: " + pair.Seed()) | |
log.Println("public key: " + pair.Address()) | |
return pair | |
} | |
func requestTestCredits(address string) { | |
client := http.Client{Timeout: 90 * time.Second} | |
resp, err := client.Get("https://horizon-testnet.stellar.org/friendbot?addr=" + address) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer resp.Body.Close() | |
_, err = ioutil.ReadAll(resp.Body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
func awaitTestBalance(address string) { | |
var lastErr error | |
var errorCount int | |
for errorCount < 20 { | |
a, err := horizon.DefaultTestNetClient.LoadAccount(address) | |
if err != nil { | |
x, ok := err.(*horizon.Error) | |
if !ok { | |
log.Fatalf("failed to load account: %s", err) | |
} | |
for k, v := range x.Problem.Extras { | |
log.Printf("%s:%s", k, v) | |
} | |
lastErr = err | |
errorCount++ | |
time.Sleep(500 * time.Millisecond) | |
continue | |
} | |
for _, balance := range a.Balances { | |
log.Printf("++checking balance: %v", balance) | |
if balance.Balance == "" { | |
continue | |
} | |
v, _ := strconv.ParseFloat(balance.Balance, 64) | |
if balance.Asset.Type == "native" && v > 0. { | |
return | |
} | |
} | |
time.Sleep(500 * time.Millisecond) | |
} | |
log.Fatalf("Aborting wait for test balance: %s", lastErr) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment