// SignAndSubmitRawTransaction will: // - update sequence number of the transaction to the current one, // - sign it, // - submit it to the network. func (ts *TransactionSubmitter) SignAndSubmitRawTransaction(seed string, tx *xdr.Transaction) (response horizon.SubmitTransactionResponse, err error) { account, err := ts.GetAccount(seed) if err != nil { return } account.Mutex.Lock() account.SequenceNumber++ tx.SeqNum = xdr.SequenceNumber(account.SequenceNumber) account.Mutex.Unlock() hash, err := TransactionHash(tx, ts.Network.Passphrase) if err != nil { ts.log.Print("Error calculating transaction hash") return } sig, err := account.Keypair.SignDecorated(hash[:]) if err != nil { ts.log.Print("Error signing a transaction") return } envelopeXdr := xdr.TransactionEnvelope{ Tx: *tx, Signatures: []xdr.DecoratedSignature{sig}, } txeB64, err := xdr.MarshalBase64(envelopeXdr) if err != nil { ts.log.Print("Cannot encode transaction envelope") return } transactionHashBytes, err := TransactionHash(tx, ts.Network.Passphrase) if err != nil { ts.log.WithFields(logrus.Fields{"err": err}).Warn("Error calculating tx hash") return } sentTransaction := &entities.SentTransaction{ TransactionID: hex.EncodeToString(transactionHashBytes[:]), Status: entities.SentTransactionStatusSending, Source: account.Keypair.Address(), SubmittedAt: ts.now(), EnvelopeXdr: txeB64, } err = ts.EntityManager.Persist(sentTransaction) if err != nil { return } response, err = ts.Horizon.SubmitTransaction(txeB64) if err != nil { ts.log.Error("Error submitting transaction ", err) return } if response.Ledger != nil { sentTransaction.MarkSucceeded(*response.Ledger) } else { var result string if response.Extras != nil { result = response.Extras.ResultXdr } else { result = "<empty>" } sentTransaction.MarkFailed(result) } err = ts.EntityManager.Persist(sentTransaction) if err != nil { return } // Sync sequence number if response.Extras != nil && response.Extras.ResultXdr == "AAAAAAAAAAD////7AAAAAA==" { account.Mutex.Lock() ts.log.Print("Syncing sequence number for ", account.Keypair.Address()) accountResponse, err2 := ts.Horizon.LoadAccount(account.Keypair.Address()) if err2 != nil { ts.log.Error("Error updating sequence number ", err) } else { account.SequenceNumber, _ = strconv.ParseUint(accountResponse.SequenceNumber, 10, 64) } account.Mutex.Unlock() } return }
// MutateTransaction for Sequence sets the SeqNum on the transaction. func (m Sequence) MutateTransaction(o *xdr.Transaction) error { o.SeqNum = xdr.SequenceNumber(m.Sequence) return nil }