Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

txnbuild: enables multiple signatures #1198

Merged
merged 7 commits into from
Apr 30, 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
11 changes: 8 additions & 3 deletions txnbuild/account_merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
// AccountMerge represents the Stellar merge account operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type AccountMerge struct {
Destination string
Destination string
SourceAccount Account
}

// BuildXDR for AccountMerge returns a fully configured XDR Operation.
Expand All @@ -22,6 +23,10 @@ func (am *AccountMerge) BuildXDR() (xdr.Operation, error) {

opType := xdr.OperationTypeAccountMerge
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, am.SourceAccount)
return op, nil
}
15 changes: 10 additions & 5 deletions txnbuild/allow_trust.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
// AllowTrust represents the Stellar allow trust operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type AllowTrust struct {
Trustor string
Type Asset
Authorize bool
Trustor string
Type Asset
Authorize bool
SourceAccount Account
}

// BuildXDR for AllowTrust returns a fully configured XDR Operation.
Expand Down Expand Up @@ -44,6 +45,10 @@ func (at *AllowTrust) BuildXDR() (xdr.Operation, error) {

opType := xdr.OperationTypeAllowTrust
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, at.SourceAccount)
return op, nil
}
11 changes: 8 additions & 3 deletions txnbuild/bump_sequence.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import (
// BumpSequence represents the Stellar bump sequence operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type BumpSequence struct {
BumpTo int64
BumpTo int64
SourceAccount Account
}

// BuildXDR for BumpSequence returns a fully configured XDR Operation.
func (bs *BumpSequence) BuildXDR() (xdr.Operation, error) {
opType := xdr.OperationTypeBumpSequence
xdrOp := xdr.BumpSequenceOp{BumpTo: xdr.SequenceNumber(bs.BumpTo)}
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, bs.SourceAccount)
return op, nil
}
13 changes: 9 additions & 4 deletions txnbuild/change_trust.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
// ChangeTrust represents the Stellar change trust operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type ChangeTrust struct {
Line Asset
Limit string
Line Asset
Limit string
SourceAccount Account
}

// RemoveTrustlineOp returns a ChangeTrust operation to remove the trustline of the described asset,
Expand Down Expand Up @@ -43,6 +44,10 @@ func (ct *ChangeTrust) BuildXDR() (xdr.Operation, error) {
Limit: xdrLimit,
}
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, ct.SourceAccount)
return xdr.Operation{Body: body}, nil
}
5 changes: 4 additions & 1 deletion txnbuild/cmd/demo/operations/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,10 @@ func deleteTrustline(source *hProtocol.Account, asset txnbuild.Asset, signer Acc
}

func deleteOffer(source *hProtocol.Account, offerID int64, signer Account) (string, error) {
deleteOffer := txnbuild.DeleteOfferOp(offerID)
deleteOffer, err := txnbuild.DeleteOfferOp(offerID)
if err != nil {
return "", errors.Wrap(err, "building offer")
}

tx := txnbuild.Transaction{
SourceAccount: source,
Expand Down
13 changes: 9 additions & 4 deletions txnbuild/create_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
// CreateAccount represents the Stellar create account operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type CreateAccount struct {
Destination string
Amount string
Destination string
Amount string
SourceAccount Account
}

// BuildXDR for CreateAccount returns a fully configured XDR Operation.
Expand All @@ -29,6 +30,10 @@ func (ca *CreateAccount) BuildXDR() (xdr.Operation, error) {

opType := xdr.OperationTypeCreateAccount
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, ca.SourceAccount)
return op, nil
}
17 changes: 11 additions & 6 deletions txnbuild/create_passive_offer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
// CreatePassiveSellOffer represents the Stellar create passive offer operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type CreatePassiveSellOffer struct {
Selling Asset
Buying Asset
Amount string
Price string
Selling Asset
Buying Asset
Amount string
Price string
SourceAccount Account
}

// BuildXDR for CreatePassiveSellOffer returns a fully configured XDR Operation.
Expand Down Expand Up @@ -47,6 +48,10 @@ func (cpo *CreatePassiveSellOffer) BuildXDR() (xdr.Operation, error) {

opType := xdr.OperationTypeCreatePassiveSellOffer
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, cpo.SourceAccount)
return op, nil
}
9 changes: 6 additions & 3 deletions txnbuild/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ func ExampleManageSellOffer() {
buying := CreditAsset{"ABCD", "GAS4V4O2B7DW5T7IQRPEEVCRXMDZESKISR7DVIGKZQYYV3OSQ5SH5LVP"}
sellAmount := "100"
price := "0.01"
op := CreateOfferOp(selling, buying, sellAmount, price)
op, err := CreateOfferOp(selling, buying, sellAmount, price)
check(err)

tx := Transaction{
SourceAccount: &sourceAccount,
Expand All @@ -329,7 +330,8 @@ func ExampleManageSellOffer_deleteOffer() {
check(err)

offerID := int64(2921622)
op := DeleteOfferOp(offerID)
op, err := DeleteOfferOp(offerID)
check(err)

tx := Transaction{
SourceAccount: &sourceAccount,
Expand Down Expand Up @@ -357,7 +359,8 @@ func ExampleManageSellOffer_updateOffer() {
sellAmount := "50"
price := "0.02"
offerID := int64(2497628)
op := UpdateOfferOp(selling, buying, sellAmount, price, offerID)
op, err := UpdateOfferOp(selling, buying, sellAmount, price, offerID)
check(err)

tx := Transaction{
SourceAccount: &sourceAccount,
Expand Down
14 changes: 5 additions & 9 deletions txnbuild/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,14 @@ func newKeypair(seed string) *keypair.Full {
return myKeypair.(*keypair.Full)
}

func buildSignEncode(tx Transaction, kp *keypair.Full, t *testing.T) (txeBase64 string) {
var err error
err = tx.Build()
assert.NoError(t, err)

err = tx.Sign(kp)
assert.NoError(t, err)
func buildSignEncode(t *testing.T, tx Transaction, kps ...*keypair.Full) string {
assert.NoError(t, tx.Build())
assert.NoError(t, tx.Sign(kps...))

txeBase64, err = tx.Base64()
txeBase64, err := tx.Base64()
assert.NoError(t, err)

return
return txeBase64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to return explicitly here, then you should remove the named return in the function definition.

}

func check(err error) {
Expand Down
12 changes: 9 additions & 3 deletions txnbuild/inflation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@ import (

// Inflation represents the Stellar inflation operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type Inflation struct{}
type Inflation struct {
SourceAccount Account
}

// BuildXDR for Inflation returns a fully configured XDR Operation.
func (inf *Inflation) BuildXDR() (xdr.Operation, error) {
opType := xdr.OperationTypeInflation
body, err := xdr.NewOperationBody(opType, nil)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, inf.SourceAccount)
return op, nil
}
13 changes: 9 additions & 4 deletions txnbuild/manage_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
// ManageData represents the Stellar manage data operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type ManageData struct {
Name string
Value []byte
Name string
Value []byte
SourceAccount Account
}

// BuildXDR for ManageData returns a fully configured XDR Operation.
Expand All @@ -26,6 +27,10 @@ func (md *ManageData) BuildXDR() (xdr.Operation, error) {

opType := xdr.OperationTypeManageData
body, err := xdr.NewOperationBody(opType, xdrOp)

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, md.SourceAccount)
return op, nil
}
61 changes: 46 additions & 15 deletions txnbuild/manage_offer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,78 @@ import (
)

//CreateOfferOp returns a ManageSellOffer operation to create a new offer, by
// setting the OfferID to "0".
func CreateOfferOp(selling, buying Asset, amount, price string) ManageSellOffer {
return ManageSellOffer{
// setting the OfferID to "0". The sourceAccount is optional, and if not provided,
// will be that of the surrounding transaction.
func CreateOfferOp(selling, buying Asset, amount, price string, sourceAccount ...Account) (ManageSellOffer, error) {
if len(sourceAccount) > 1 {
return ManageSellOffer{}, errors.New("offer can't have multiple source accounts")
}
offer := ManageSellOffer{
Selling: selling,
Buying: buying,
Amount: amount,
Price: price,
OfferID: 0,
}
if len(sourceAccount) == 1 {
offer.SourceAccount = sourceAccount[0]
}
return offer, nil
}

//UpdateOfferOp returns a ManageSellOffer operation to update an offer.
func UpdateOfferOp(selling, buying Asset, amount, price string, offerID int64) ManageSellOffer {
return ManageSellOffer{
// UpdateOfferOp returns a ManageSellOffer operation to update an offer.
// The sourceAccount is optional, and if not provided, will be that of
// the surrounding transaction.
func UpdateOfferOp(selling, buying Asset, amount, price string, offerID int64, sourceAccount ...Account) (ManageSellOffer, error) {
if len(sourceAccount) > 1 {
return ManageSellOffer{}, errors.New("offer can't have multiple source accounts")
}
offer := ManageSellOffer{
Selling: selling,
Buying: buying,
Amount: amount,
Price: price,
OfferID: offerID,
}
if len(sourceAccount) == 1 {
offer.SourceAccount = sourceAccount[0]
}
return offer, nil
}

//DeleteOfferOp returns a ManageSellOffer operation to delete an offer, by
// setting the Amount to "0".
func DeleteOfferOp(offerID int64) ManageSellOffer {
// setting the Amount to "0". The sourceAccount is optional, and if not provided,
// will be that of the surrounding transaction.
func DeleteOfferOp(offerID int64, sourceAccount ...Account) (ManageSellOffer, error) {
// It turns out Stellar core doesn't care about any of these fields except the amount.
// However, Horizon will reject ManageSellOffer if it is missing fields.
// Horizon will also reject if Buying == Selling.
// Therefore unfortunately we have to make up some dummy values here.
return ManageSellOffer{
if len(sourceAccount) > 1 {
return ManageSellOffer{}, errors.New("offer can't have multiple source accounts")
}
offer := ManageSellOffer{
Selling: NativeAsset{},
Buying: CreditAsset{Code: "FAKE", Issuer: "GBAQPADEYSKYMYXTMASBUIS5JI3LMOAWSTM2CHGDBJ3QDDPNCSO3DVAA"},
Amount: "0",
Price: "1",
OfferID: offerID,
}
if len(sourceAccount) == 1 {
offer.SourceAccount = sourceAccount[0]
}
return offer, nil
}

// ManageSellOffer represents the Stellar manage offer operation. See
// https://www.stellar.org/developers/guides/concepts/list-of-operations.html
type ManageSellOffer struct {
Selling Asset
Buying Asset
Amount string
Price string
OfferID int64
Selling Asset
Buying Asset
Amount string
Price string
OfferID int64
SourceAccount Account
}

// BuildXDR for ManageSellOffer returns a fully configured XDR Operation.
Expand Down Expand Up @@ -87,6 +113,11 @@ func (mo *ManageSellOffer) BuildXDR() (xdr.Operation, error) {
OfferId: xdr.Int64(mo.OfferID),
}
body, err := xdr.NewOperationBody(opType, xdrOp)
if err != nil {
return xdr.Operation{}, errors.Wrap(err, "failed to build XDR OperationBody")
}

return xdr.Operation{Body: body}, errors.Wrap(err, "failed to build XDR OperationBody")
op := xdr.Operation{Body: body}
SetOpSourceAccount(&op, mo.SourceAccount)
return op, nil
}
10 changes: 10 additions & 0 deletions txnbuild/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ import (
type Operation interface {
BuildXDR() (xdr.Operation, error)
}

// SetOpSourceAccount sets the source account ID on an Operation.
func SetOpSourceAccount(op *xdr.Operation, sourceAccount Account) {
if sourceAccount == nil {
return
}
var opSourceAccountID xdr.AccountId
opSourceAccountID.SetAddress(sourceAccount.GetAccountID())
op.SourceAccount = &opSourceAccountID
}
Loading