mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-19 13:44:11 +01:00
Invoke onCoinsSent() when receiving a pending transaction that spends the wallets coins.
This commit is contained in:
parent
cf76cf064f
commit
6b2275890a
@ -281,9 +281,13 @@ public class Wallet implements Serializable {
|
||||
return;
|
||||
}
|
||||
|
||||
BigInteger value = tx.getValueSentToMe(this);
|
||||
log.info("Received a pending transaction {} that sends us {} BTC", tx.getHashAsString(),
|
||||
Utils.bitcoinValueToFriendlyString(value));
|
||||
BigInteger valueSentToMe = tx.getValueSentToMe(this);
|
||||
BigInteger valueSentFromMe = tx.getValueSentFromMe(this);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info(String.format("Received a pending transaction %s that spends %s BTC and sends us %s BTC", tx.getHashAsString(),
|
||||
Utils.bitcoinValueToFriendlyString(valueSentFromMe),
|
||||
Utils.bitcoinValueToFriendlyString(valueSentToMe)));
|
||||
}
|
||||
|
||||
// Mark the tx as having been seen but is not yet in the chain. This will normally have been done already by
|
||||
// the Peer before we got to this point, but in some cases (unit tests, other sources of transactions) it may
|
||||
@ -293,15 +297,19 @@ public class Wallet implements Serializable {
|
||||
currentConfidence == TransactionConfidence.ConfidenceType.NOT_SEEN_IN_CHAIN : currentConfidence;
|
||||
tx.getConfidence().setConfidenceType(TransactionConfidence.ConfidenceType.NOT_SEEN_IN_CHAIN);
|
||||
|
||||
BigInteger balance = getBalance();
|
||||
|
||||
// If this tx spends any of our unspent outputs, mark them as spent now, then add to the pending pool. This
|
||||
// ensures that if some other client that has our keys broadcasts a spend we stay in sync. Also updates the
|
||||
// timestamp on the transaction.
|
||||
commitTx(tx);
|
||||
|
||||
// Event listeners may re-enter so we cannot make assumptions about wallet state after this loop completes.
|
||||
BigInteger balance = getBalance();
|
||||
BigInteger newBalance = balance.add(value);
|
||||
invokeOnCoinsReceived(tx, balance, newBalance);
|
||||
BigInteger newBalance = balance.add(valueSentToMe).subtract(valueSentFromMe);
|
||||
if (valueSentToMe.compareTo(BigInteger.ZERO) > 0)
|
||||
invokeOnCoinsReceived(tx, balance, newBalance);
|
||||
if (valueSentFromMe.compareTo(BigInteger.ZERO) > 0)
|
||||
invokeOnCoinsSent(tx, balance, newBalance);
|
||||
}
|
||||
|
||||
// Boilerplate that allows event listeners to delete themselves during execution, and auto locks the listener.
|
||||
|
@ -39,7 +39,7 @@ public interface WalletEventListener {
|
||||
* @param wallet The wallet object that received the coins
|
||||
* @param tx The transaction which sent us the coins.
|
||||
* @param prevBalance Balance before the coins were received.
|
||||
* @param newBalance Current balance of the wallet.
|
||||
* @param newBalance Current balance of the wallet. This is the 'estimated' balance.
|
||||
*/
|
||||
void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance);
|
||||
|
||||
@ -57,7 +57,7 @@ public interface WalletEventListener {
|
||||
* @param wallet The wallet object that this callback relates to (that sent the coins).
|
||||
* @param tx The transaction that sent the coins to someone else.
|
||||
* @param prevBalance The wallets balance before this transaction was seen.
|
||||
* @param newBalance The wallets balance after this transaction was seen (should be less than prevBalance).
|
||||
* @param newBalance The wallets balance after this transaction was seen. This is the 'estimated' balance.
|
||||
*/
|
||||
void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance);
|
||||
|
||||
|
@ -101,25 +101,6 @@ public class WalletTest {
|
||||
assertEquals(v1, wallet.getBalance());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listeners() throws Exception {
|
||||
final Transaction fakeTx = createFakeTx(params, Utils.toNanoCoins(1, 0), myAddress);
|
||||
final boolean[] didRun = new boolean[1];
|
||||
WalletEventListener listener = new AbstractWalletEventListener() {
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||
assertTrue(prevBalance.equals(BigInteger.ZERO));
|
||||
assertTrue(newBalance.equals(Utils.toNanoCoins(1, 0)));
|
||||
assertEquals(tx, fakeTx); // Same object.
|
||||
assertEquals(w, wallet); // Same object.
|
||||
didRun[0] = true;
|
||||
}
|
||||
};
|
||||
wallet.addEventListener(listener);
|
||||
wallet.receiveFromBlock(fakeTx, null, BlockChain.NewBlockType.BEST_CHAIN);
|
||||
assertTrue(didRun[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void balance() throws Exception {
|
||||
// Receive 5 coins then half a coin.
|
||||
@ -394,19 +375,34 @@ public class WalletTest {
|
||||
@Test
|
||||
public void pending2() throws Exception {
|
||||
// Check that if we receive a pending tx we did not send, it updates our spent flags correctly.
|
||||
|
||||
final Transaction txn[] = new Transaction[1];
|
||||
final BigInteger bigints[] = new BigInteger[2];
|
||||
wallet.addEventListener(new AbstractWalletEventListener() {
|
||||
@Override
|
||||
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
|
||||
txn[0] = tx;
|
||||
bigints[0] = prevBalance;
|
||||
bigints[1] = newBalance;
|
||||
}
|
||||
});
|
||||
// Receive some coins.
|
||||
BigInteger nanos = Utils.toNanoCoins(1, 0);
|
||||
Transaction t1 = createFakeTx(params, nanos, myAddress);
|
||||
StoredBlock b1 = createFakeBlock(params, blockStore, t1).storedBlock;
|
||||
wallet.receiveFromBlock(t1, b1, BlockChain.NewBlockType.BEST_CHAIN);
|
||||
assertEquals(nanos, wallet.getBalance());
|
||||
// Create a spend with them, but don't commit it (ie it's from somewhere else but using our keys).
|
||||
Transaction t2 = wallet.createSend(new ECKey().toAddress(params), nanos);
|
||||
// Create a spend with them, but don't commit it (ie it's from somewhere else but using our keys). This TX
|
||||
// will have change as we don't spend our entire balance.
|
||||
BigInteger halfNanos = Utils.toNanoCoins(0, 50);
|
||||
Transaction t2 = wallet.createSend(new ECKey().toAddress(params), halfNanos);
|
||||
// Now receive it as pending.
|
||||
wallet.receivePending(t2);
|
||||
// Our balance is now zero.
|
||||
assertEquals(BigInteger.ZERO, wallet.getBalance());
|
||||
// We received an onCoinsSent() callback.
|
||||
assertEquals(t2, txn[0]);
|
||||
assertEquals(nanos, bigints[0]);
|
||||
assertEquals(halfNanos, bigints[1]);
|
||||
// Our balance is now 0.50 BTC
|
||||
assertEquals(halfNanos, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -517,7 +513,7 @@ public class WalletTest {
|
||||
// Test migration from appearsIn to appearsInHashes
|
||||
Transaction tx1 = createFakeTx(params, Utils.toNanoCoins(1, 0), myAddress);
|
||||
StoredBlock b1 = createFakeBlock(params, blockStore, tx1).storedBlock;
|
||||
tx1 .appearsIn = new HashSet<StoredBlock>();
|
||||
tx1.appearsIn = new HashSet<StoredBlock>();
|
||||
tx1.appearsIn.add(b1);
|
||||
assertEquals(1, tx1.getAppearsInHashes().size());
|
||||
assertTrue(tx1.getAppearsInHashes().contains(b1.getHeader().getHash()));
|
||||
|
Loading…
Reference in New Issue
Block a user