mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 02:05:53 +00:00
Clean up Coin API for multiplications and divisions.
This commit is contained in:
parent
eb81b0c815
commit
48a76a8a03
@ -82,20 +82,20 @@ public final class Coin implements Comparable<Coin>, Serializable {
|
||||
return new Coin(LongMath.checkedSubtract(this.value, value.value));
|
||||
}
|
||||
|
||||
public Coin multiply(final Coin value) {
|
||||
return new Coin(LongMath.checkedMultiply(this.value, value.value));
|
||||
public Coin multiply(final long factor) {
|
||||
return new Coin(LongMath.checkedMultiply(this.value, factor));
|
||||
}
|
||||
|
||||
public Coin multiply(final long value) {
|
||||
return new Coin(LongMath.checkedMultiply(this.value, value));
|
||||
public Coin divide(final long divisor) {
|
||||
return new Coin(this.value / divisor);
|
||||
}
|
||||
|
||||
public Coin divide(final Coin value) {
|
||||
return new Coin(this.value / value.value);
|
||||
public Coin[] divideAndRemainder(final long divisor) {
|
||||
return new Coin[] { new Coin(this.value / divisor), new Coin(this.value % divisor) };
|
||||
}
|
||||
|
||||
public Coin[] divideAndRemainder(final Coin value) {
|
||||
return new Coin[] { new Coin(this.value / value.value), new Coin(this.value % value.value) };
|
||||
public long divide(final Coin divisor) {
|
||||
return this.value / divisor.value;
|
||||
}
|
||||
|
||||
public Coin shiftLeft(final int n) {
|
||||
@ -156,10 +156,9 @@ public final class Coin implements Comparable<Coin>, Serializable {
|
||||
checkArgument(cents < 100);
|
||||
checkArgument(cents >= 0);
|
||||
checkArgument(coins >= 0);
|
||||
checkArgument(coins < NetworkParameters.MAX_MONEY.divide(COIN).longValue());
|
||||
Coin bi = Coin.valueOf(coins).multiply(COIN);
|
||||
bi = bi.add(Coin.valueOf(cents).multiply(CENT));
|
||||
return bi;
|
||||
final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents));
|
||||
checkArgument(coin.compareTo(NetworkParameters.MAX_MONEY) <= 0);
|
||||
return coin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +133,7 @@ public abstract class NetworkParameters implements Serializable {
|
||||
/**
|
||||
* The maximum money to be generated
|
||||
*/
|
||||
public static final Coin MAX_MONEY = new Coin("21000000", 10).multiply(COIN);
|
||||
public static final Coin MAX_MONEY = COIN.multiply(21000000);
|
||||
|
||||
/** Alias for TestNet3Params.get(), use that instead. */
|
||||
@Deprecated
|
||||
|
@ -205,7 +205,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
|
||||
// clients wrongness in order to ensure we're considered standard. A better formula would either estimate the
|
||||
// size of data needed to satisfy all different script types, or just hard code 33 below.
|
||||
final long size = this.bitcoinSerialize().length + 148;
|
||||
Coin[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(Coin.valueOf(1000));
|
||||
Coin[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(1000);
|
||||
return nonDustAndRemainder[1].equals(Coin.ZERO) ? nonDustAndRemainder[0] : nonDustAndRemainder[0].add(Coin.ONE);
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ public class TransactionOutput extends ChildMessage implements Serializable {
|
||||
* {@link Transaction#MIN_NONDUST_OUTPUT}.
|
||||
*/
|
||||
public Coin getMinNonDustValue() {
|
||||
return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(3)));
|
||||
return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(3));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2448,7 +2448,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
||||
// Check if we need additional fee due to the transaction's size
|
||||
int size = tx.bitcoinSerialize().length;
|
||||
size += estimateBytesForSigning(coinSelection);
|
||||
Coin fee = baseFee.add(Coin.valueOf((size / 1000) + 1).multiply(feePerKb));
|
||||
Coin fee = baseFee.add(feePerKb.multiply((size / 1000) + 1));
|
||||
output.setValue(output.getValue().subtract(fee));
|
||||
// Check if we need additional fee due to the output's value
|
||||
if (output.getValue().compareTo(Coin.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
|
||||
@ -3564,7 +3564,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
||||
Coin fees = req.fee == null ? Coin.ZERO : req.fee;
|
||||
if (lastCalculatedSize > 0) {
|
||||
// If the size is exactly 1000 bytes then we'll over-pay, but this should be rare.
|
||||
fees = fees.add(Coin.valueOf((lastCalculatedSize / 1000) + 1).multiply(req.feePerKb));
|
||||
fees = fees.add(req.feePerKb.multiply((lastCalculatedSize / 1000) + 1));
|
||||
} else {
|
||||
fees = fees.add(req.feePerKb); // First time around the loop.
|
||||
}
|
||||
|
@ -1562,7 +1562,7 @@ public class WalletTest extends TestWithWallet {
|
||||
// We optimize for priority, so the output selected should be the largest one
|
||||
assertEquals(Coin.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue()));
|
||||
|
||||
SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(Coin.valueOf(2)).multiply(Coin.valueOf(2))));
|
||||
SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(Coin.valueOf(2)).multiply(2)));
|
||||
request7.tx.addOutput(CENT.subtract(ONE), notMyAddr);
|
||||
wallet.completeTx(request7);
|
||||
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.fee);
|
||||
@ -1782,13 +1782,13 @@ public class WalletTest extends TestWithWallet {
|
||||
request20.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
wallet.completeTx(request20);
|
||||
// 4kb tx.
|
||||
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4)), request20.fee);
|
||||
assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(4), request20.fee);
|
||||
assertEquals(2, request20.tx.getInputs().size());
|
||||
Coin outValue20 = ZERO;
|
||||
for (TransactionOutput out : request20.tx.getOutputs())
|
||||
outValue20 = outValue20.add(out.getValue());
|
||||
// This time the fee we wanted to pay was more, so that should be what we paid
|
||||
assertEquals(outValue20, COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4))));
|
||||
assertEquals(outValue20, COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(4)));
|
||||
|
||||
// Same as request 19, but make the change 0 (so it doesnt force fee) and make us require min fee as a
|
||||
// result of an output < CENT.
|
||||
@ -1820,7 +1820,7 @@ public class WalletTest extends TestWithWallet {
|
||||
// Now reset request19 and give it a fee per kb
|
||||
request25.tx.clearInputs();
|
||||
request25 = SendRequest.forTx(request25.tx);
|
||||
request25.feePerKb = CENT.divide(Coin.valueOf(3));
|
||||
request25.feePerKb = CENT.divide(3);
|
||||
request25.ensureMinRequiredFee = false;
|
||||
request25.shuffleOutputs = false;
|
||||
wallet.completeTx(request25);
|
||||
@ -1875,7 +1875,7 @@ public class WalletTest extends TestWithWallet {
|
||||
// Generate a ton of small outputs
|
||||
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
|
||||
int i = 0;
|
||||
while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).longValue()) {
|
||||
while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)) {
|
||||
Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, myAddress, notMyAddr);
|
||||
tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique
|
||||
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
|
||||
@ -1912,13 +1912,13 @@ public class WalletTest extends TestWithWallet {
|
||||
|
||||
//
|
||||
SendRequest request4 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(ONE));
|
||||
request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(Coin.valueOf(request3.tx.bitcoinSerialize().length));
|
||||
request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(request3.tx.bitcoinSerialize().length);
|
||||
wallet.completeTx(request4);
|
||||
assertEquals(ONE, request4.fee);
|
||||
assertEquals(request4.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2
|
||||
|
||||
// Give us a few more inputs...
|
||||
while (wallet.getBalance().compareTo(CENT.shiftLeft(1)) < 0) {
|
||||
while (wallet.getBalance().compareTo(CENT.multiply(2)) < 0) {
|
||||
Transaction tx3 = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, myAddress, notMyAddr);
|
||||
tx3.getInput(0).setSequenceNumber(i++); // Keep every transaction unique
|
||||
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
|
||||
@ -1956,8 +1956,8 @@ public class WalletTest extends TestWithWallet {
|
||||
// Generate a ton of small outputs
|
||||
StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1);
|
||||
int i = 0;
|
||||
while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN)).longValue()) {
|
||||
Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN), myAddress, notMyAddr);
|
||||
while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(10))) {
|
||||
Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(10), myAddress, notMyAddr);
|
||||
tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique
|
||||
wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i);
|
||||
}
|
||||
@ -2006,7 +2006,7 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2);
|
||||
|
||||
// Create a transaction who's max size could be up to 1000 (if signatures were maximum size)
|
||||
SendRequest request1 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(Coin.valueOf(17))));
|
||||
SendRequest request1 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(17)));
|
||||
for (int i = 0; i < 16; i++)
|
||||
request1.tx.addOutput(CENT, notMyAddr);
|
||||
request1.tx.addOutput(new TransactionOutput(params, request1.tx, CENT, new byte[16]));
|
||||
@ -2025,7 +2025,7 @@ public class WalletTest extends TestWithWallet {
|
||||
wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 3);
|
||||
|
||||
// Create a transaction who's max size could be up to 1000 (if signatures were maximum size)
|
||||
SendRequest request2 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(Coin.valueOf(17))));
|
||||
SendRequest request2 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(17)));
|
||||
for (int i = 0; i < 16; i++)
|
||||
request2.tx.addOutput(CENT, notMyAddr);
|
||||
request2.tx.addOutput(new TransactionOutput(params, request2.tx, CENT, new byte[16]));
|
||||
|
@ -519,11 +519,11 @@ public class ChannelConnectionTest extends TestWithWallet {
|
||||
|
||||
// Now check that if the server has a lower min size than what we are willing to spend, we do actually open
|
||||
// a channel of that size.
|
||||
sendMoneyToWallet(COIN.multiply(TEN), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
sendMoneyToWallet(COIN.multiply(10), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||
|
||||
pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
|
||||
server = pair.server;
|
||||
final Coin myValue = COIN.multiply(TEN);
|
||||
final Coin myValue = COIN.multiply(10);
|
||||
client = new PaymentChannelClient(wallet, myKey, myValue, Sha256Hash.ZERO_HASH, pair.clientRecorder);
|
||||
client.connectionOpen();
|
||||
server.connectionOpen();
|
||||
|
@ -95,7 +95,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
@Test
|
||||
public void stateErrors() throws Exception {
|
||||
PaymentChannelClientState channelState = new PaymentChannelClientState(wallet, myKey, serverKey,
|
||||
COIN.multiply(TEN), 20);
|
||||
COIN.multiply(10), 20);
|
||||
assertEquals(PaymentChannelClientState.State.NEW, channelState.getState());
|
||||
try {
|
||||
channelState.getMultisigContract();
|
||||
@ -165,7 +165,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash()));
|
||||
|
||||
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
|
||||
Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
|
||||
Coin size = halfCoin.divide(100);
|
||||
Coin totalPayment = Coin.ZERO;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin();
|
||||
@ -195,10 +195,10 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
// Create a block with the payment transaction in it and give it to both wallets
|
||||
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), reserializedCloseTx));
|
||||
|
||||
assertEquals(size.multiply(Coin.valueOf(5)), serverWallet.getBalance());
|
||||
assertEquals(size.multiply(5), serverWallet.getBalance());
|
||||
assertEquals(0, serverWallet.getPendingTransactions().size());
|
||||
|
||||
assertEquals(COIN.subtract(size.multiply(Coin.valueOf(5))), wallet.getBalance());
|
||||
assertEquals(COIN.subtract(size.multiply(5)), wallet.getBalance());
|
||||
assertEquals(0, wallet.getPendingTransactions().size());
|
||||
assertEquals(3, wallet.getTransactions(false).size());
|
||||
|
||||
@ -234,12 +234,12 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState());
|
||||
|
||||
clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()),
|
||||
CENT.divide(Coin.valueOf(2)), EXPIRE_TIME);
|
||||
CENT.divide(2), EXPIRE_TIME);
|
||||
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
|
||||
assertEquals(CENT.divide(Coin.valueOf(2)), clientState.getTotalValue());
|
||||
assertEquals(CENT.divide(2), clientState.getTotalValue());
|
||||
clientState.initiate();
|
||||
// We will have to pay min_tx_fee twice - both the multisig contract and the refund tx
|
||||
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2)));
|
||||
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2));
|
||||
assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState());
|
||||
|
||||
// Send the refund tx from client to server and get back the signature.
|
||||
@ -270,8 +270,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
|
||||
|
||||
// Pay a tiny bit
|
||||
serverState.incrementPayment(CENT.divide(Coin.valueOf(2)).subtract(CENT.divide(TEN)),
|
||||
clientState.incrementPaymentBy(CENT.divide(TEN)).signature.encodeToBitcoin());
|
||||
serverState.incrementPayment(CENT.divide(2).subtract(CENT.divide(10)),
|
||||
clientState.incrementPaymentBy(CENT.divide(10)).signature.encodeToBitcoin());
|
||||
|
||||
// Advance time until our we get close enough to lock time that server should rebroadcast
|
||||
Utils.rollMockClock(60*60*22);
|
||||
@ -314,7 +314,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), multisigContract,clientBroadcastedRefund));
|
||||
|
||||
// Make sure we actually had to pay what initialize() told us we would
|
||||
assertEquals(wallet.getBalance(), CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2))));
|
||||
assertEquals(wallet.getBalance(), CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2)));
|
||||
|
||||
try {
|
||||
// After its expired, we cant still increment payment
|
||||
@ -452,7 +452,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertEquals(PaymentChannelServerState.State.READY, serverState.getState());
|
||||
|
||||
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
|
||||
Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
|
||||
Coin size = halfCoin.divide(100);
|
||||
Coin totalPayment = Coin.ZERO;
|
||||
try {
|
||||
clientState.incrementPaymentBy(COIN);
|
||||
@ -561,7 +561,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertEquals(PaymentChannelClientState.State.NEW, clientState.getState());
|
||||
// We'll have to pay REFERENCE_DEFAULT_MIN_TX_FEE twice (multisig+refund), and we'll end up getting back nearly nothing...
|
||||
clientState.initiate();
|
||||
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2)));
|
||||
assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2));
|
||||
assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState());
|
||||
|
||||
// Now actually use a more useful CENT
|
||||
@ -704,8 +704,8 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertTrue(e.getMessage().contains("more in fees"));
|
||||
}
|
||||
|
||||
signature = clientState.incrementPaymentBy(Coin.ONE.shiftLeft(1)).signature.encodeToBitcoin();
|
||||
totalRefund = totalRefund.subtract(Coin.ONE.shiftLeft(1));
|
||||
signature = clientState.incrementPaymentBy(Coin.valueOf(2)).signature.encodeToBitcoin();
|
||||
totalRefund = totalRefund.subtract(Coin.valueOf(2));
|
||||
serverState.incrementPayment(totalRefund, signature);
|
||||
|
||||
// And settle the channel.
|
||||
@ -773,7 +773,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
||||
assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash()));
|
||||
|
||||
// Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins.
|
||||
Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN);
|
||||
Coin size = halfCoin.divide(100);
|
||||
Coin totalPayment = Coin.ZERO;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin();
|
||||
|
@ -97,7 +97,7 @@ public class DefaultCoinSelectorTest extends TestWithWallet {
|
||||
Transaction t1 = checkNotNull(sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN));
|
||||
// Padding block.
|
||||
wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore).storedBlock);
|
||||
final Coin TWO_COINS = COIN.multiply(Coin.valueOf(2));
|
||||
final Coin TWO_COINS = COIN.multiply(2);
|
||||
Transaction t2 = checkNotNull(sendMoneyToWallet(TWO_COINS, AbstractBlockChain.NewBlockType.BEST_CHAIN));
|
||||
Transaction t3 = checkNotNull(sendMoneyToWallet(CENT, AbstractBlockChain.NewBlockType.BEST_CHAIN));
|
||||
|
||||
|
@ -40,7 +40,6 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.google.bitcoin.core.Coin.CENT;
|
||||
import static com.google.bitcoin.core.Coin.TEN;
|
||||
|
||||
/**
|
||||
* Simple client that connects to the given host, opens a channel, and pays one cent.
|
||||
@ -123,7 +122,7 @@ public class ExamplePaymentChannelClient {
|
||||
// we are not allowed to have payment channels that pay nothing at all.
|
||||
log.info("Success! Trying to make {} micropayments. Already paid {} satoshis on this channel",
|
||||
times, client.state().getValueSpent());
|
||||
final Coin MICROPAYMENT_SIZE = CENT.divide(TEN);
|
||||
final Coin MICROPAYMENT_SIZE = CENT.divide(10);
|
||||
for (int i = 0; i < times; i++) {
|
||||
try {
|
||||
// Wait because the act of making a micropayment is async, and we're not allowed to overlap.
|
||||
|
Loading…
x
Reference in New Issue
Block a user