+// SortByTimestamp implements sort.Interface for AnnotatedTx slices
+type SortByTimestamp []*query.AnnotatedTx
+
+func (a SortByTimestamp) Len() int { return len(a) }
+func (a SortByTimestamp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a SortByTimestamp) Less(i, j int) bool { return a[i].Timestamp > a[j].Timestamp }
+
+// AddUnconfirmedTx handle wallet status update when tx add into txpool
+func (w *Wallet) AddUnconfirmedTx(txD *protocol.TxDesc) {
+ if err := w.saveUnconfirmedTx(txD.Tx); err != nil {
+ log.WithField("err", err).Error("wallet fail on saveUnconfirmedTx")
+ }
+
+ utxos := txOutToUtxos(txD.Tx, txD.StatusFail, 0)
+ utxos = w.filterAccountUtxo(utxos)
+ w.AccountMgr.AddUnconfirmedUtxo(utxos)
+}
+
+// GetUnconfirmedTxs get account unconfirmed transactions, filter transactions by accountID when accountID is not empty
+func (w *Wallet) GetUnconfirmedTxs(accountID string) ([]*query.AnnotatedTx, error) {
+ annotatedTxs := []*query.AnnotatedTx{}
+ txIter := w.DB.IteratorPrefix([]byte(UnconfirmedTxPrefix))
+ defer txIter.Release()
+
+ for txIter.Next() {
+ annotatedTx := &query.AnnotatedTx{}
+ if err := json.Unmarshal(txIter.Value(), &annotatedTx); err != nil {
+ return nil, err
+ }
+
+ if accountID == "" || findTransactionsByAccount(annotatedTx, accountID) {
+ annotateTxsAsset(w, []*query.AnnotatedTx{annotatedTx})
+ annotatedTxs = append([]*query.AnnotatedTx{annotatedTx}, annotatedTxs...)
+ }
+ }
+
+ sort.Sort(SortByTimestamp(annotatedTxs))
+ return annotatedTxs, nil
+}
+
+// GetUnconfirmedTxByTxID get unconfirmed transaction by txID
+func (w *Wallet) GetUnconfirmedTxByTxID(txID string) (*query.AnnotatedTx, error) {
+ annotatedTx := &query.AnnotatedTx{}
+ txInfo := w.DB.Get(calcUnconfirmedTxKey(txID))
+ if txInfo == nil {
+ return nil, fmt.Errorf("No transaction(tx_id=%s) from txpool", txID)
+ }
+
+ if err := json.Unmarshal(txInfo, annotatedTx); err != nil {
+ return nil, err
+ }
+
+ annotateTxsAsset(w, []*query.AnnotatedTx{annotatedTx})
+ return annotatedTx, nil
+}
+
+// RemoveUnconfirmedTx handle wallet status update when tx removed from txpool
+func (w *Wallet) RemoveUnconfirmedTx(txD *protocol.TxDesc) {
+ if !w.checkRelatedTransaction(txD.Tx) {
+ return
+ }
+ w.DB.Delete(calcUnconfirmedTxKey(txD.Tx.ID.String()))
+ w.AccountMgr.RemoveUnconfirmedUtxo(txD.Tx.ResultIds)
+}
+
+func (w *Wallet) buildAnnotatedUnconfirmedTx(tx *types.Tx) *query.AnnotatedTx {