diff --git a/build/bump_sequence.go b/build/bump_sequence.go new file mode 100644 index 0000000000..0df311b387 --- /dev/null +++ b/build/bump_sequence.go @@ -0,0 +1,54 @@ +package build + +import ( + "github.com/stellar/go/support/errors" + "github.com/stellar/go/xdr" +) + +// BumpSequence groups the creation of a new BumpSequenceBuilder with a call +// to Mutate. Requires the BumpTo mutator to be set. +func BumpSequence(muts ...interface{}) (result BumpSequenceBuilder) { + result.Mutate(muts...) + return +} + +// BumpSequenceMutator is a interface that wraps the +// MutateBumpSequence operation. types may implement this interface to +// specify how they modify an xdr.BumpSequenceOp object +type BumpSequenceMutator interface { + MutateBumpSequence(*xdr.BumpSequenceOp) error +} + +// BumpSequenceBuilder helps to build BumpSequenceOp structs. +type BumpSequenceBuilder struct { + O xdr.Operation + BS xdr.BumpSequenceOp + Err error +} + +// Mutate applies the provided mutators to this builder's payment or operation. +func (b *BumpSequenceBuilder) Mutate(muts ...interface{}) { + for _, m := range muts { + var err error + switch mut := m.(type) { + case BumpSequenceMutator: + err = mut.MutateBumpSequence(&b.BS) + case OperationMutator: + err = mut.MutateOperation(&b.O) + default: + err = errors.New("Mutator type not allowed") + } + + if err != nil { + b.Err = errors.Wrap(err, "BumpSequenceBuilder error") + return + } + } +} + +// MutateBumpSequence for BumpTo sets the BumpSequenceOp's +// StartingBalance field +func (m BumpTo) MutateBumpSequence(o *xdr.BumpSequenceOp) (err error) { + o.BumpTo = xdr.SequenceNumber(m) + return +} diff --git a/build/bump_sequence_test.go b/build/bump_sequence_test.go new file mode 100644 index 0000000000..7131616818 --- /dev/null +++ b/build/bump_sequence_test.go @@ -0,0 +1,56 @@ +package build + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/stellar/go/xdr" +) + +var _ = Describe("BumpSequenceBuilder Mutators", func() { + + var ( + subject BumpSequenceBuilder + mut interface{} + + address = "GAXEMCEXBERNSRXOEKD4JAIKVECIXQCENHEBRVSPX2TTYZPMNEDSQCNQ" + bad = "foo" + ) + + JustBeforeEach(func() { + subject = BumpSequenceBuilder{} + subject.Mutate(mut) + }) + + Describe("BumpTo", func() { + BeforeEach(func() { mut = BumpTo(9223372036854775807) }) + + It("succeeds", func() { + Expect(subject.Err).NotTo(HaveOccurred()) + }) + + It("sets the value to the correct xdr.SequenceNumber", func() { + Expect(subject.BS.BumpTo).To(Equal(xdr.SequenceNumber(9223372036854775807))) + }) + }) + + Describe("SourceAccount", func() { + Context("using a valid stellar address", func() { + BeforeEach(func() { mut = SourceAccount{address} }) + + It("succeeds", func() { + Expect(subject.Err).NotTo(HaveOccurred()) + }) + + It("sets the destination to the correct xdr.AccountId", func() { + var aid xdr.AccountId + aid.SetAddress(address) + Expect(subject.O.SourceAccount.MustEd25519()).To(Equal(aid.MustEd25519())) + }) + }) + + Context("using an invalid value", func() { + BeforeEach(func() { mut = SourceAccount{bad} }) + It("failed", func() { Expect(subject.Err).To(HaveOccurred()) }) + }) + }) +}) diff --git a/build/main.go b/build/main.go index 8f29796ce4..b821a1c461 100644 --- a/build/main.go +++ b/build/main.go @@ -68,6 +68,9 @@ type AutoSequence struct { SequenceProvider } +// BumpTo sets sequence number on BumpSequence operation +type BumpTo int64 + // NativeAsset is a helper method to create native Asset object func NativeAsset() Asset { return Asset{Native: true} diff --git a/build/main_test.go b/build/main_test.go index 1e7a00957b..514675c084 100644 --- a/build/main_test.go +++ b/build/main_test.go @@ -88,6 +88,42 @@ func ExampleCreateAccount() { // Output: tx base64: AAAAADZY/nWY0gx6beMpf4S8Ur0qHsjA8fbFtBzBx1cbQzHwAAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAALSRpLtCLv2eboZlEiHDSGR6Hb+zZL92fbSdNpObeE0EAAAAAHc1lAAAAAAAAAAABG0Mx8AAAAEDiHQEurLITX87zmkEi8Rrcf5wGp1JrLnSDoTJiN+yNjJZVF3WcBJgoGyIJ3NJo+tNmTqALVrJziiiZGdoukxcN } +// ExampleBumpSequence creates a transaction to bump sequence of a given account. It then +// encodes the transaction into a base64 string capable of being submitted to stellar-core. It uses +// the transaction builder system. +func ExampleBumpSequence() { + seed := "SDOTALIMPAM2IV65IOZA7KZL7XWZI5BODFXTRVLIHLQZQCKK57PH5F3H" + tx, err := Transaction( + SourceAccount{seed}, + Sequence{1}, + TestNetwork, + BumpSequence( + BumpTo(5), + ), + ) + + if err != nil { + fmt.Println(err) + return + } + + txe, err := tx.Sign(seed) + if err != nil { + fmt.Println(err) + return + } + + txeB64, err := txe.Base64() + + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("tx base64: %s", txeB64) + // Output: tx base64: AAAAADZY/nWY0gx6beMpf4S8Ur0qHsjA8fbFtBzBx1cbQzHwAAAAZAAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAsAAAAAAAAABQAAAAAAAAABG0Mx8AAAAEAZkMhF/4tin/eiAw+yj13iQ9xApg0wadSyIMdk2D73RvwvgxwqfAGF6qmL1d8qqrjClZ7Vi0MYBDPxOQchwMQA +} + // ExamplePayment creates and signs a native-asset Payment, encodes it into a base64 string capable of // being submitted to stellar-core. It uses the transaction builder system. func ExamplePayment() { diff --git a/build/transaction.go b/build/transaction.go index 0d28e8ccc0..d3936baff2 100644 --- a/build/transaction.go +++ b/build/transaction.go @@ -138,6 +138,18 @@ func (m AutoSequence) MutateTransaction(o *TransactionBuilder) error { return nil } +// MutateTransaction for BumpSequenceBuilder causes the underylying BumpSequenceOp +// to be added to the operation list for the provided transaction +func (m BumpSequenceBuilder) MutateTransaction(o *TransactionBuilder) error { + if m.Err != nil { + return m.Err + } + + m.O.Body, m.Err = xdr.NewOperationBody(xdr.OperationTypeBumpSequence, m.BS) + o.TX.Operations = append(o.TX.Operations, m.O) + return m.Err +} + // MutateTransaction for ChangeTrustBuilder causes the underylying // CreateAccountOp to be added to the operation list for the provided // transaction