// Hash returns the hash of this builder's transaction. func (b *TransactionBuilder) Hash() ([32]byte, error) { var txBytes bytes.Buffer _, err := fmt.Fprint(&txBytes, b.NetworkID) if err != nil { return [32]byte{}, err } _, err = xdr.Marshal(&txBytes, xdr.EnvelopeTypeEnvelopeTypeTx) if err != nil { return [32]byte{}, err } _, err = xdr.Marshal(&txBytes, b.TX) if err != nil { return [32]byte{}, err } return stellarbase.Hash(txBytes.Bytes()), nil }
func TestDecode(t *testing.T) { Convey("Decode XDR Enum", t, func() { // works for positive values var op xdr.OperationType r := bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x00}) xdr.Unmarshal(r, &op) So(op, ShouldEqual, xdr.OperationTypeCreateAccount) r = bytes.NewReader([]byte{0x00, 0x00, 0x00, 0x08}) xdr.Unmarshal(r, &op) So(op, ShouldEqual, xdr.OperationTypeAccountMerge) // works for negative values var trc xdr.TransactionResultCode r = bytes.NewReader([]byte{0xFF, 0xFF, 0xFF, 0xFF}) xdr.Unmarshal(r, &trc) So(trc, ShouldEqual, xdr.TransactionResultCodeTxFailed) r = bytes.NewReader([]byte{0x00, 0xFF, 0xFF, 0xFF}) _, err := xdr.Unmarshal(r, &op) So(err, ShouldNotBeNil) }) Convey("Decodes Memo", t, func() { data := "AAAAAA==" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var memo xdr.Memo _, err := xdr.Unmarshal(b64r, &memo) So(err, ShouldBeNil) }) Convey("Decodes AccountID", t, func() { data := "AAAAAK6jei3jmoI8TGlD/egc37PXtHKKzWV8wViZBaCu5L5M" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var id xdr.AccountId _, err := xdr.Unmarshal(b64r, &id) So(err, ShouldBeNil) }) Convey("Decodes OperationBody", t, func() { data := "AAAAAAAAAACuo3ot45qCPExpQ/3oHN+z17Ryis1lfMFYmQWgruS+TAAAAAA7msoA" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var body xdr.OperationBody _, err := xdr.Unmarshal(b64r, &body) So(err, ShouldBeNil) }) Convey("Decode TransactionResultPair", t, func() { data := "mf13Xm7tPjMcffhLVA2VXbTs6fV9IpgHFZGKy3zlu/QAAAAAAAAACgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA==" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var trp xdr.TransactionResultPair _, err := xdr.Unmarshal(b64r, &trp) So(err, ShouldBeNil) So(len(trp.TransactionHash), ShouldEqual, 32) So(trp.Result.FeeCharged, ShouldEqual, 10) trr := trp.Result.Result So(trr.Code, ShouldEqual, xdr.TransactionResultCodeTxSuccess) So(trr.Results, ShouldNotBeNil) r := trr.MustResults() So(len(r), ShouldEqual, 1) opr := r[0] So(opr.Code, ShouldEqual, xdr.OperationResultCodeOpInner) oprr := opr.MustTr() So(oprr.Type, ShouldEqual, xdr.OperationTypeCreateAccount) cr := oprr.MustCreateAccountResult() So(cr.Code, ShouldEqual, xdr.CreateAccountResultCodeCreateAccountSuccess) So(func() { oprr.MustAccountMergeResult() }, ShouldPanic) }) Convey("Decode TransactionEnvelope", t, func() { data := "AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAACgAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAEAKZ7IPj/46PuWU6ZOtyMosctNAkXRNX9WCAI5RnfRk+AyxDLoDZP/9l3NvsxQtWj9juQOuoBlFLnWu8intgxQA" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var txe xdr.TransactionEnvelope _, err := xdr.Unmarshal(b64r, &txe) So(err, ShouldBeNil) So(len(txe.Signatures), ShouldEqual, 1) tx := txe.Tx So(tx.Fee, ShouldEqual, 10) So(tx.SeqNum, ShouldEqual, 1) So(tx.Memo.Type, ShouldEqual, xdr.MemoTypeMemoNone) op := tx.Operations[0] So(op.SourceAccount, ShouldBeNil) p := op.Body.MustCreateAccountOp() So(p.StartingBalance, ShouldEqual, 1000000000) }) Convey("Decode TransactionMeta", t, func() { data := "AAAAAAAAAAEAAAABAAAAAgAAAAAAAAAAYvwdC9CRsrYcDdZWNGsqaNfTR8bywsjubQRHAlb8BfcBY0V4XYn/9gAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAAAAAACAAAAAAAAAACuo3ot45qCPExpQ/3oHN+z17Ryis1lfMFYmQWgruS+TAAAAAA7msoAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAABi/B0L0JGythwN1lY0aypo19NHxvLCyO5tBEcCVvwF9wFjRXgh7zX2AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA==" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var m xdr.TransactionMeta _, err := xdr.Unmarshal(b64r, &m) So(err, ShouldBeNil) tm := m.MustV0() So(len(tm.Changes), ShouldEqual, 1) So(len(tm.Operations), ShouldEqual, 1) So(len(tm.Operations[0].Changes), ShouldEqual, 2) }) Convey("Roundtrip TransactionEnvelope", t, func() { data := "AAAAAGL8HQvQkbK2HA3WVjRrKmjX00fG8sLI7m0ERwJW/AX3AAAACgAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAArqN6LeOagjxMaUP96Bzfs9e0corNZXzBWJkFoK7kvkwAAAAAO5rKAAAAAAAAAAABVvwF9wAAAEAKZ7IPj/46PuWU6ZOtyMosctNAkXRNX9WCAI5RnfRk+AyxDLoDZP/9l3NvsxQtWj9juQOuoBlFLnWu8intgxQA" rawr := strings.NewReader(data) b64r := base64.NewDecoder(base64.StdEncoding, rawr) var txe xdr.TransactionEnvelope n, err := xdr.Unmarshal(b64r, &txe) So(err, ShouldBeNil) var output bytes.Buffer b64w := base64.NewEncoder(base64.StdEncoding, &output) n2, err := xdr.Marshal(b64w, txe) So(n2, ShouldEqual, n) So(output.String(), ShouldEqual, data) }) }
// ExampleLowLevelTransaction creates and signs a simple transaction, and then // encodes it into a hex string capable of being submitted to stellar-core. // // It uses the low-level xdr facilities to create the transaction. func ExampleLowLevelTransaction() { spub, spriv, err := GenerateKeyFromSeed("SA26PHIKZM6CXDGR472SSGUQQRYXM6S437ZNHZGRM6QA4FOPLLLFRGDX") if err != nil { panic(err) } dpub, _, err := GenerateKeyFromSeed("SBQHO2IMYKXAYJFCWGXC7YKLJD2EGDPSK3IUDHVJ6OOTTKLSCK6Z6POM") if err != nil { panic(err) } asset, err := xdr.NewAsset(xdr.AssetTypeAssetTypeNative, nil) if err != nil { panic(err) } destination, err := AddressToAccountId(dpub.Address()) if err != nil { panic(err) } op := xdr.PaymentOp{ Destination: destination, Asset: asset, Amount: 50 * 10000000, } memo, err := xdr.NewMemo(xdr.MemoTypeMemoNone, nil) source, err := AddressToAccountId(spub.Address()) if err != nil { panic(err) } body, err := xdr.NewOperationBody(xdr.OperationTypePayment, op) if err != nil { panic(err) } tx := xdr.Transaction{ SourceAccount: source, Fee: 10, SeqNum: xdr.SequenceNumber(1), Memo: memo, Operations: []xdr.Operation{ {Body: body}, }, } var txBytes bytes.Buffer _, err = xdr.Marshal(&txBytes, tx) if err != nil { panic(err) } txHash := Hash(txBytes.Bytes()) signature := spriv.Sign(txHash[:]) ds := xdr.DecoratedSignature{ Hint: spriv.Hint(), Signature: xdr.Signature(signature[:]), } txe := xdr.TransactionEnvelope{ Tx: tx, Signatures: []xdr.DecoratedSignature{ds}, } var txeBytes bytes.Buffer _, err = xdr.Marshal(&txeBytes, txe) if err != nil { panic(err) } txeB64 := base64.StdEncoding.EncodeToString(txeBytes.Bytes()) fmt.Printf("tx base64: %s", txeB64) // Output: tx base64: AAAAAAU08yUQ8sHqhY8j9mXWwERfHC/3cKFSe/spAr0rGtO2AAAACgAAAAAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAA+fnTe7/v4whpBUx96oj92jfZPz7S00l3O2xeyeqWIA0AAAAAAAAAAB3NZQAAAAAAAAAAATXnnQoAAABAieruUIGcQH6RlQ+prYflPFU3nED2NvWhtaC+tgnKsqgiKURK4xo/W7EgH0+I6aQok52awbE+ksOxEQ5MLJ9eAw== }