@@ -124,6 +124,20 @@ type Server struct {
124124 walletDir string
125125}
126126
127+ func isStaleWalletTransactionError (err error ) bool {
128+ return err != nil && strings .Contains (err .Error (), "No such mempool or blockchain transaction" )
129+ }
130+
131+ func isNonFinalTransactionError (err error ) bool {
132+ return err != nil && strings .Contains (err .Error (), "non-final" )
133+ }
134+
135+ func isInsufficientReplacementFeeError (err error ) bool {
136+ return err != nil &&
137+ strings .Contains (err .Error (), "insufficient fee" ) &&
138+ strings .Contains (err .Error (), "rejecting replacement" )
139+ }
140+
127141// CreateBitcoinCoreWallet implements walletv1connect.WalletServiceHandler.
128142// Test endpoint to verify descriptor import to Bitcoin Core.
129143func (s * Server ) CreateBitcoinCoreWallet (ctx context.Context , c * connect.Request [pb.CreateBitcoinCoreWalletRequest ]) (* connect.Response [pb.CreateBitcoinCoreWalletResponse ], error ) {
@@ -802,6 +816,9 @@ func (s *Server) ListTransactions(ctx context.Context, c *connect.Request[pb.Lis
802816
803817 txs , err := wallet .ListTransactions (ctx , connect .NewRequest (& validatorpb.ListTransactionsRequest {}))
804818 if err != nil {
819+ if isStaleWalletTransactionError (err ) {
820+ return connect .NewResponse (& pb.ListTransactionsResponse {}), nil
821+ }
805822 return nil , fmt .Errorf ("enforcer/wallet: could not list transactions: %w" , err )
806823 }
807824
@@ -1067,6 +1084,12 @@ func (s *Server) ListSidechainDeposits(ctx context.Context, c *connect.Request[p
10671084 if strings .Contains (err .Error (), "Missing value from db" ) {
10681085 return connect .NewResponse (& pb.ListSidechainDepositsResponse {}), nil
10691086 }
1087+ // The enforcer can remember a deposit txid after Bitcoin Core has dropped
1088+ // it from both the mempool and chain. Keep the sidechains UI usable while
1089+ // the wallet history is stale.
1090+ if isStaleWalletTransactionError (err ) {
1091+ return connect .NewResponse (& pb.ListSidechainDepositsResponse {}), nil
1092+ }
10701093 return nil , fmt .Errorf ("enforcer/wallet: could not list sidechain deposits: %w" , err )
10711094 }
10721095
@@ -1142,6 +1165,12 @@ func (s *Server) CreateSidechainDeposit(ctx context.Context, c *connect.Request[
11421165 FeeSats : & wrapperspb.UInt64Value {Value : uint64 (fee )},
11431166 }))
11441167 if err != nil {
1168+ if isNonFinalTransactionError (err ) {
1169+ return nil , connect .NewError (connect .CodeFailedPrecondition , errors .New ("deposit transaction is not final yet; wait for the next mainchain block, then check deposits or retry" ))
1170+ }
1171+ if isInsufficientReplacementFeeError (err ) {
1172+ return nil , connect .NewError (connect .CodeFailedPrecondition , errors .New ("a deposit from this wallet is already waiting in the mainchain mempool; wait for the next mainchain block, then check deposits or retry" ))
1173+ }
11451174 return nil , fmt .Errorf ("enforcer/wallet: could not create deposit transaction: %w" , err )
11461175 }
11471176
@@ -1843,7 +1872,11 @@ func (s *Server) GetStats(ctx context.Context, c *connect.Request[pb.GetStatsReq
18431872 // 2. Get all wallet transactions and count them
18441873 txs , err := wallet .ListTransactions (ctx , connect .NewRequest (& validatorpb.ListTransactionsRequest {}))
18451874 if err != nil {
1846- return nil , err
1875+ if isStaleWalletTransactionError (err ) {
1876+ txs = connect .NewResponse (& validatorpb.ListTransactionsResponse {})
1877+ } else {
1878+ return nil , err
1879+ }
18471880 }
18481881 transactionCount := int64 (len (txs .Msg .Transactions ))
18491882
@@ -1864,7 +1897,11 @@ func (s *Server) GetStats(ctx context.Context, c *connect.Request[pb.GetStatsReq
18641897 // 3. Get all sidechain deposit transactions and sum their amounts
18651898 sidechainDeposits , err := wallet .ListSidechainDepositTransactions (ctx , connect .NewRequest (& validatorpb.ListSidechainDepositTransactionsRequest {}))
18661899 if err != nil {
1867- return nil , err
1900+ if isStaleWalletTransactionError (err ) || strings .Contains (err .Error (), "Missing value from db" ) {
1901+ sidechainDeposits = connect .NewResponse (& validatorpb.ListSidechainDepositTransactionsResponse {})
1902+ } else {
1903+ return nil , err
1904+ }
18681905 }
18691906 var depositSum int64
18701907 var depositSumLast30Days int64
0 commit comments