Skip to content

Commit 1ab5b5d

Browse files
author
Ed Gamble
authored
Merge pull request #233 from breadwallet/feature/CORE-525
CORE-525: Handle Pending Transactions
2 parents 973b0f1 + b1ca944 commit 1ab5b5d

File tree

14 files changed

+172
-95
lines changed

14 files changed

+172
-95
lines changed

Java/CoreCrypto/src/main/java/com/breadwallet/corecrypto/System.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.breadwallet.corenative.crypto.BRCryptoWalletEvent;
2424
import com.breadwallet.corenative.crypto.BRCryptoWalletManager;
2525
import com.breadwallet.corenative.crypto.BRCryptoWalletManagerEvent;
26+
import com.breadwallet.corenative.support.BRConstants;
2627
import com.breadwallet.corenative.utility.Cookie;
2728
import com.breadwallet.crypto.AddressScheme;
2829
import com.breadwallet.crypto.TransferState;
@@ -1688,9 +1689,13 @@ private static void btcGetTransactions(Cookie context, BRCryptoWalletManager cor
16881689
if (optWalletManager.isPresent()) {
16891690
WalletManager walletManager = optWalletManager.get();
16901691

1691-
system.query.getTransactions(walletManager.getNetwork().getUids(), addresses, begBlockNumberUnsigned,
1692-
endBlockNumberUnsigned, true,
1693-
false, new CompletionHandler<List<Transaction>, QueryError>() {
1692+
system.query.getTransactions(walletManager.getNetwork().getUids(),
1693+
addresses,
1694+
begBlockNumberUnsigned.equals(BRConstants.BLOCK_HEIGHT_UNBOUND) ? null : begBlockNumberUnsigned,
1695+
endBlockNumberUnsigned.equals(BRConstants.BLOCK_HEIGHT_UNBOUND) ? null : endBlockNumberUnsigned,
1696+
true,
1697+
false,
1698+
new CompletionHandler<List<Transaction>, QueryError>() {
16941699
@Override
16951700
public void handleData(List<Transaction> transactions) {
16961701
Log.d(TAG, "BRCryptoCWMBtcGetTransactionsCallback received transactions");
@@ -2379,9 +2384,14 @@ private static void genGetTransactions(Cookie context, BRCryptoWalletManager cor
23792384
if (optWalletManager.isPresent()) {
23802385
WalletManager walletManager = optWalletManager.get();
23812386

2382-
system.query.getTransactions(walletManager.getNetwork().getUids(), Collections.singletonList(address), begBlockNumberUnsigned,
2383-
endBlockNumberUnsigned, true,
2384-
false, new CompletionHandler<List<Transaction>, QueryError>() {
2387+
system.query.getTransactions(
2388+
walletManager.getNetwork().getUids(),
2389+
Collections.singletonList(address),
2390+
begBlockNumberUnsigned.equals(BRConstants.BLOCK_HEIGHT_UNBOUND) ? null : begBlockNumberUnsigned,
2391+
endBlockNumberUnsigned.equals(BRConstants.BLOCK_HEIGHT_UNBOUND) ? null : endBlockNumberUnsigned,
2392+
true,
2393+
false,
2394+
new CompletionHandler<List<Transaction>, QueryError>() {
23852395
@Override
23862396
public void handleData(List<Transaction> transactions) {
23872397
Log.d(TAG, "BRCryptoCWMGenGetTransactionsCallback received transactions");

Java/CoreCrypto/src/main/java/com/breadwallet/corecrypto/WalletSweeper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ private void initAsBtc(BlockchainDb bdb,
159159
Network network = manager.getNetwork();
160160
String address = getAddress();
161161

162-
bdb.getTransactions(network.getUids(),
162+
bdb.getTransactions(
163+
network.getUids(),
163164
Collections.singletonList(address),
164165
UnsignedLong.ZERO,
165166
network.getHeight(),
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Created by Michael Carrara <michael.carrara@breadwallet.com> on 9/20/18.
3+
* Copyright (c) 2018 Breadwinner AG. All right reserved.
4+
*
5+
* See the LICENSE file at the project root for license information.
6+
* See the CONTRIBUTORS file at the project root for a list of contributors.
7+
*/
8+
package com.breadwallet.corenative.support;
9+
10+
import com.google.common.primitives.UnsignedLong;
11+
12+
public final class BRConstants {
13+
14+
public static final UnsignedLong BLOCK_HEIGHT_UNBOUND = UnsignedLong.MAX_VALUE;
15+
16+
private BRConstants() {}
17+
}

Java/Crypto/src/main/java/com/breadwallet/crypto/blockchaindb/BlockchainDb.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ public void getTransfer(String id, CompletionHandler<Transfer, QueryError> handl
205205
// Transactions
206206

207207
public void getTransactions(String id, List<String> addresses,
208-
UnsignedLong beginBlockNumber,
209-
UnsignedLong endBlockNumber,
208+
@Nullable UnsignedLong beginBlockNumber,
209+
@Nullable UnsignedLong endBlockNumber,
210210
boolean includeRaw,
211211
boolean includeProof,
212212
CompletionHandler<List<Transaction>, QueryError> handler) {
@@ -215,8 +215,8 @@ public void getTransactions(String id, List<String> addresses,
215215
}
216216

217217
public void getTransactions(String id, List<String> addresses,
218-
UnsignedLong beginBlockNumber,
219-
UnsignedLong endBlockNumber,
218+
@Nullable UnsignedLong beginBlockNumber,
219+
@Nullable UnsignedLong endBlockNumber,
220220
boolean includeRaw,
221221
boolean includeProof,
222222
@Nullable Integer maxPageSize,

Java/Crypto/src/main/java/com/breadwallet/crypto/blockchaindb/apis/bdb/TransactionApi.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,13 @@ public TransactionApi(BdbApiClient jsonClient, ExecutorService executorService)
4242
this.executorService = executorService;
4343
}
4444

45-
public void getTransactions(String id, List<String> addresses, UnsignedLong beginBlockNumber, UnsignedLong endBlockNumber,
46-
boolean includeRaw, boolean includeProof, @Nullable Integer maxPageSize,
45+
public void getTransactions(String id,
46+
List<String> addresses,
47+
@Nullable UnsignedLong beginBlockNumber,
48+
@Nullable UnsignedLong endBlockNumber,
49+
boolean includeRaw,
50+
boolean includeProof,
51+
@Nullable Integer maxPageSize,
4752
CompletionHandler<List<Transaction>, QueryError> handler) {
4853
List<List<String>> chunkedAddressesList = Lists.partition(addresses, ADDRESS_COUNT);
4954
GetChunkedCoordinator<String, Transaction> coordinator = new GetChunkedCoordinator<>(chunkedAddressesList, handler);
@@ -55,9 +60,9 @@ public void getTransactions(String id, List<String> addresses, UnsignedLong begi
5560
paramsBuilder.put("blockchain_id", id);
5661
paramsBuilder.put("include_proof", String.valueOf(includeProof));
5762
paramsBuilder.put("include_raw", String.valueOf(includeRaw));
58-
paramsBuilder.put("start_height", beginBlockNumber.toString());
59-
paramsBuilder.put("end_height", endBlockNumber.toString());
60-
if (null != maxPageSize) paramsBuilder.put("max_page_size", maxPageSize.toString());
63+
if (beginBlockNumber != null) paramsBuilder.put("start_height", beginBlockNumber.toString());
64+
if (endBlockNumber != null) paramsBuilder.put("end_height", endBlockNumber.toString());
65+
if (maxPageSize != null) paramsBuilder.put("max_page_size", maxPageSize.toString());
6166
for (String address : chunkedAddresses) paramsBuilder.put("address", address);
6267
ImmutableMultimap<String, String> params = paramsBuilder.build();
6368

Swift/BRCrypto/BRCryptoSystem.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,8 +1391,8 @@ extension System {
13911391

13921392
manager.query.getTransactions (blockchainId: manager.network.uids,
13931393
addresses: addresses,
1394-
begBlockNumber: begBlockNumber,
1395-
endBlockNumber: endBlockNumber,
1394+
begBlockNumber: (begBlockNumber == BLOCK_HEIGHT_UNBOUND ? nil : begBlockNumber),
1395+
endBlockNumber: (endBlockNumber == BLOCK_HEIGHT_UNBOUND ? nil : endBlockNumber),
13961396
includeRaw: true) {
13971397
(res: Result<[BlockChainDB.Model.Transaction], BlockChainDB.QueryError>) in
13981398
defer { cryptoWalletManagerGive (cwm!) }
@@ -1433,7 +1433,9 @@ extension System {
14331433
defer { cryptoWalletManagerGive (cwm!) }
14341434
res.resolve(
14351435
success: { (_) in cwmAnnounceSubmitTransferSuccess (cwm, sid) },
1436-
failure: { (_) in cwmAnnounceSubmitTransferFailure (cwm, sid) })
1436+
failure: { (e) in
1437+
print ("SYS: BTC: SubmitTransaction: Error: \(e)")
1438+
cwmAnnounceSubmitTransferFailure (cwm, sid) })
14371439
}
14381440
})
14391441
}
@@ -1742,8 +1744,8 @@ extension System {
17421744

17431745
manager.query.getTransactions (blockchainId: manager.network.uids,
17441746
addresses: [asUTF8String(address!)],
1745-
begBlockNumber: begBlockNumber,
1746-
endBlockNumber: endBlockNumber,
1747+
begBlockNumber: (begBlockNumber == BLOCK_HEIGHT_UNBOUND ? nil : begBlockNumber),
1748+
endBlockNumber: (endBlockNumber == BLOCK_HEIGHT_UNBOUND ? nil : endBlockNumber),
17471749
includeRaw: true) {
17481750
(res: Result<[BlockChainDB.Model.Transaction], BlockChainDB.QueryError>) in
17491751
defer { cryptoWalletManagerGive(cwm) }

Swift/BRCrypto/BRCryptoTransfer.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,15 @@ public enum TransferSubmitError: Equatable, Error {
300300
}
301301
}
302302

303+
extension TransferSubmitError: CustomStringConvertible {
304+
public var description: String {
305+
switch self {
306+
case .unknown: return ".unknwon"
307+
case let .posix(errno, message): return ".posix(\(errno):\(message ?? ""))"
308+
}
309+
}
310+
}
311+
303312
///
304313
/// A TransferState represents the states in Transfer's 'life-cycle'
305314
///
@@ -339,7 +348,7 @@ extension TransferState: CustomStringConvertible {
339348
case .submitted: return "Submitted"
340349
case .pending: return "Pending"
341350
case .included: return "Included"
342-
case .failed: return "Failed"
351+
case .failed (let error): return "Failed (\(error))"
343352
case .deleted: return "Deleted"
344353
}
345354
}

Swift/BRCrypto/common/BRBlockChainDB.swift

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -795,8 +795,8 @@ public class BlockChainDB {
795795

796796
public func getTransactions (blockchainId: String,
797797
addresses: [String],
798-
begBlockNumber: UInt64,
799-
endBlockNumber: UInt64,
798+
begBlockNumber: UInt64? = nil,
799+
endBlockNumber: UInt64? = nil,
800800
includeRaw: Bool = false,
801801
includeProof: Bool = false,
802802
maxPageSize: Int? = nil,
@@ -807,58 +807,65 @@ public class BlockChainDB {
807807
var error: QueryError? = nil
808808
var results = [Model.Transaction]()
809809

810-
for addresses in addresses.chunked(into: BlockChainDB.ADDRESS_COUNT) {
811-
if nil != error { break }
812-
var queryKeys = ["blockchain_id", "start_height", "end_height", "include_proof", "include_raw"]
813-
+ Array (repeating: "address", count: addresses.count)
814-
815-
var queryVals = [blockchainId, "0", "0", includeProof.description, includeRaw.description]
816-
+ addresses
810+
let queryKeysBase = [
811+
"blockchain_id",
812+
begBlockNumber.map { (_) in "start_height" },
813+
endBlockNumber.map { (_) in "end_height" },
814+
"include_proof",
815+
"include_raw",
816+
maxPageSize.map { (_) in "max_page_size" }]
817+
.compactMap { $0 } // Remove `nil` from {beg,end}BlockNumber
818+
819+
let queryValsBase: [String] = [
820+
blockchainId,
821+
begBlockNumber.map { $0.description },
822+
endBlockNumber.map { $0.description },
823+
includeProof.description,
824+
includeRaw.description,
825+
maxPageSize.map { $0.description }]
826+
.compactMap { $0 } // Remove `nil` from {beg,end}BlockNumber
817827

818-
if let maxPageSize = maxPageSize {
819-
queryKeys += ["max_page_size"]
820-
queryVals += [String(maxPageSize)]
821-
}
822-
823-
let semaphore = DispatchSemaphore (value: 0)
828+
let semaphore = DispatchSemaphore (value: 0)
829+
var nextURL: URL? = nil
824830

825-
var nextURL: URL? = nil
831+
func handleResult (more: URL?, res: Result<[JSON], QueryError>) {
832+
// Append `transactions` with the resulting transactions.
833+
results += res
834+
.flatMap { BlockChainDB.getManyExpected(data: $0, transform: Model.asTransaction) }
835+
.getWithRecovery { error = $0; return [] }
826836

827-
queryVals[1] = begBlockNumber.description
828-
queryVals[2] = endBlockNumber.description
837+
// Record if more exist
838+
nextURL = more
829839

830-
// Make the first request. Ideally we'll get all the transactions in one gulp
831-
self.bdbMakeRequest (path: "transactions", query: zip (queryKeys, queryVals)) {
832-
(more: URL?, res: Result<[JSON], QueryError>) in
840+
// signal completion
841+
semaphore.signal()
842+
}
833843

834-
// Append `transactions` with the resulting transactions.
835-
results += try! res
836-
.flatMap { BlockChainDB.getManyExpected(data: $0, transform: Model.asTransaction) }
837-
.recover { error = $0; return [] }.get()
844+
for addresses in addresses.chunked(into: BlockChainDB.ADDRESS_COUNT) {
845+
if nil != error { break }
838846

839-
nextURL = more
847+
let queryKeys = queryKeysBase + Array (repeating: "address", count: addresses.count)
848+
let queryVals = queryValsBase + addresses
840849

841-
semaphore.signal()
842-
}
850+
// Ensure a 'clean' start for this set of addresses
851+
nextURL = nil
852+
853+
// Make the first request. Ideally we'll get all the transactions in one gulp
854+
self.bdbMakeRequest (path: "transactions",
855+
query: zip (queryKeys, queryVals),
856+
completion: handleResult)
843857

844858
// Wait for the first request
845859
semaphore.wait()
846860

847861
// Loop until all 'nextURL' values are queried
848862
while let url = nextURL, nil == error {
849-
self.bdbMakeRequest (url: url, embedded: true, embeddedPath: "transactions") {
850-
(more: URL?, res: Result<[JSON], QueryError>) in
851-
852-
// Append `transactions` with the resulting transactions.
853-
results += try! res
854-
.flatMap { BlockChainDB.getManyExpected(data: $0, transform: Model.asTransaction) }
855-
.recover { error = $0; return [] }.get()
856-
857-
nextURL = more
858-
859-
semaphore.signal()
860-
}
863+
self.bdbMakeRequest (url: url,
864+
embedded: true,
865+
embeddedPath: "transactions",
866+
completion: handleResult)
861867

868+
// Wait for each subsequent result
862869
semaphore.wait()
863870
}
864871
}

0 commit comments

Comments
 (0)