public async Task update_gas_price_should_succeed_if_sending_new_transaction_succeeds() { var transactionHash = TestItem.KeccakA; var transaction = Build.A.Transaction.TestObject; var sentTransactionHash = TestItem.KeccakB; var gasPrice = 30.GWei(); _blockchainBridge.GetTransactionAsync(transactionHash) .Returns(new NdmTransaction(transaction, true, 1, TestItem.KeccakB, 1)); _blockchainBridge.SendOwnTransactionAsync(transaction).Returns(sentTransactionHash); var hash = await _transactionService.UpdateGasPriceAsync(transactionHash, gasPrice); hash.Should().Be(sentTransactionHash); transaction.GasPrice.Should().Be(gasPrice); await _blockchainBridge.Received().GetTransactionAsync(transactionHash); await _blockchainBridge.Received().GetNetworkIdAsync(); await _blockchainBridge.Received().SendOwnTransactionAsync(transaction); }
public async Task send_own_transaction_should_invoke_blockchain_bridge_send_transaction_and_return_hash() { var transaction = Build.A.Transaction.TestObject; var hash = TestItem.KeccakA; _txPoolBridge.SendTransaction(transaction, TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce).Returns(hash); var result = await _ndmBridge.SendOwnTransactionAsync(transaction); _txPoolBridge.Received().SendTransaction(transaction, TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce); result.Should().Be(hash); }
public async Task send_own_transaction_should_invoke_blockchain_bridge_send_transaction_and_return_hash() { var transaction = Build.A.Transaction.TestObject; var hash = TestItem.KeccakA; _blockchainBridge.SendTransaction(transaction, true).Returns(hash); var result = await _ndmBridge.SendOwnTransactionAsync(transaction); _blockchainBridge.Received().SendTransaction(transaction, true); result.Should().Be(hash); }
public async Task <Keccak> ClaimRefundAsync(Address onBehalfOf, RefundClaim refundClaim, UInt256 gasPrice) { byte[] txData = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimRefundSig, refundClaim.AssetId.Bytes, refundClaim.Units, refundClaim.Value, refundClaim.ExpiryTime, refundClaim.Pepper, refundClaim.Provider, onBehalfOf); Transaction transaction = new Transaction(); transaction.Value = 0; transaction.Data = txData; transaction.To = _contractAddress; transaction.SenderAddress = onBehalfOf; transaction.GasLimit = (long)GasLimit; transaction.GasPrice = gasPrice; transaction.Nonce = await _blockchainBridge.ReserveOwnTransactionNonceAsync(onBehalfOf); _wallet.Sign(transaction, await _blockchainBridge.GetNetworkIdAsync()); if (_logger.IsInfo) { _logger.Info($"Sending a refund claim transaction for {refundClaim.DepositId} to be refunded to {refundClaim.RefundTo}"); } return(await _blockchainBridge.SendOwnTransactionAsync(transaction)); }
public async Task send_own_transaction_should_invoke_proxy_eth_sendRawTransaction_and_return_hash() { var transaction = Build.A.Transaction.TestObject; var data = Rlp.Encode(transaction).Bytes; var hash = TestItem.KeccakA; _proxy.eth_sendRawTransaction(Arg.Is <byte[]>(x => x.SequenceEqual(data))) .Returns(RpcResult <Keccak> .Ok(hash)); var result = await _ndmBridge.SendOwnTransactionAsync(transaction); await _proxy.Received().eth_sendRawTransaction(Arg.Is <byte[]>(x => x.SequenceEqual(data))); result.Should().BeSameAs(hash); }
public async Task <Keccak?> MakeDepositAsync(Address onBehalfOf, Deposit deposit, UInt256 gasPrice) { var txData = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.DepositAbiSig, deposit.Id.Bytes, deposit.Units, deposit.ExpiryTime); Transaction transaction = new Transaction { Value = deposit.Value, Data = txData, To = _contractAddress, SenderAddress = onBehalfOf, GasLimit = (long)GasLimit, GasPrice = gasPrice }; // check _wallet.Sign(transaction, await _blockchainBridge.GetNetworkIdAsync()); return(await _blockchainBridge.SendOwnTransactionAsync(transaction)); }
public void Setup() { _blockchainBridge = Substitute.For <INdmBlockchainBridge>(); _repository = Substitute.For <IEthRequestRepository>(); _repository.SumDailyRequestsTotalValueAsync(Arg.Any <DateTime>()).ReturnsForAnyArgs(UInt256.Zero); _faucetAddress = Address.FromNumber(1); _maxValue = 1.Ether(); _dailyRequestsTotalValueEth = 500; _enabled = true; _timestamper = new Timestamper(); _wallet = Substitute.For <IWallet>(); _logManager = LimboLogs.Instance; _host = "127.0.0.1"; _address = Address.FromNumber(2); _value = 1.Ether(); _faucetAccount = Account.TotallyEmpty; _transactionHash = Keccak.Zero; _blockchainBridge.GetNonceAsync(_faucetAddress).Returns(UInt256.Zero); _blockchainBridge.SendOwnTransactionAsync(Arg.Any <Transaction>()).Returns(_transactionHash); }
public async Task <Keccak?> ClaimPaymentAsync(PaymentClaim paymentClaim, Address coldWalletAddress, UInt256 gasPrice) { byte[] txData = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimPaymentAbiSig, paymentClaim.AssetId.Bytes, paymentClaim.Units, paymentClaim.Value, paymentClaim.ExpiryTime, paymentClaim.Pepper, coldWalletAddress, paymentClaim.Consumer, new[] { paymentClaim.UnitsRange.From, paymentClaim.UnitsRange.To }, paymentClaim.Signature.V, paymentClaim.Signature.R, paymentClaim.Signature.S); if (_logger.IsInfo) { _logger.Info($"Sending a payment claim transaction - Range: [{paymentClaim.UnitsRange.From},{paymentClaim.UnitsRange.To}] Units: {paymentClaim.Units} to be paid out to {coldWalletAddress}"); } Transaction transaction = new Transaction { Value = 0, Data = txData, To = _contractAddress, SenderAddress = paymentClaim.Provider, GasLimit = (long)GasLimit, // when account does not exist then we pay for account creation of cold wallet GasPrice = gasPrice, Nonce = await _bridge.GetNonceAsync(paymentClaim.Provider) }; // check _wallet.Sign(transaction, await _bridge.GetNetworkIdAsync()); return(await _bridge.SendOwnTransactionAsync(transaction)); }
private async Task <Keccak> UpdateAsync(Keccak transactionHash, Action <Transaction> update) { if (transactionHash is null) { throw new ArgumentException("Transaction hash cannot be null.", nameof(transactionHash)); } var transactionDetails = await _blockchainBridge.GetTransactionAsync(transactionHash); if (transactionDetails is null) { throw new ArgumentException($"Transaction was not found for hash: '{transactionHash}'.", nameof(transactionHash)); } if (!transactionDetails.IsPending) { throw new InvalidOperationException($"Transaction with hash: '{transactionHash}' is not pending."); } var transaction = transactionDetails.Transaction; update(transaction); _wallet.Sign(transaction, await _blockchainBridge.GetNetworkIdAsync()); var hash = await _blockchainBridge.SendOwnTransactionAsync(transaction); if (hash is null) { throw new InvalidOperationException("Transaction was not sent (received an empty hash)."); } if (_logger.IsInfo) { _logger.Info($"Received a new transaction hash: '{hash}' (previous transaction hash: '{transactionHash}')."); } return(hash); }
public async Task <FaucetResponse> TryRequestEthAsync(string node, Address?address, UInt256 value) { if (!_enabled) { if (_logger.IsInfo) { _logger.Info("NDM Faucet is disabled."); } return(FaucetResponse.FaucetDisabled); } if (!_initialized) { if (_logger.IsInfo) { _logger.Info("NDM Faucet is not initialized."); } return(FaucetResponse.FaucetDisabled); } if (_today.Date != _timestamper.UtcNow.Date) { lock (_locker) { _today = _timestamper.UtcNow; _todayRequestsTotalValueWei = 0; } if (_logger.IsInfo) { _logger.Info($"NDM Faucet has updated its today's date ({_today.Date:d}) and reset the total requests value."); } } if (_faucetAddress is null || _faucetAddress == Address.Zero) { if (_logger.IsWarn) { _logger.Warn("NDM Faucet address is not set."); } return(FaucetResponse.FaucetAddressNotSet); } if (string.IsNullOrWhiteSpace(node) || address is null || address == Address.Zero) { if (_logger.IsInfo) { _logger.Info("Invalid NDM Faucet request."); } return(FaucetResponse.InvalidNodeAddress); } if (_faucetAddress == address) { if (_logger.IsInfo) { _logger.Info("NDM Faucet request cannot be processed for the same address as NDM Faucet."); } return(FaucetResponse.SameAddressAsFaucet); } if (value == 0) { if (_logger.IsInfo) { _logger.Info("NDM Faucet request cannot be processed for the zero value."); } return(FaucetResponse.ZeroValue); } if (value > _maxValue) { if (_logger.IsInfo) { _logger.Info($"NDM Faucet request from: {node} has too big value: {value} wei > {_maxValue} wei."); } return(FaucetResponse.TooBigValue); } if (_logger.IsInfo) { _logger.Info($"Received NDM Faucet request from: {node}, address: {address}, value: {value} wei."); } if (_pendingRequests.TryGetValue(node, out _)) { if (_logger.IsInfo) { _logger.Info($"NDM Faucet request from: {node} is already being processed."); } return(FaucetResponse.RequestAlreadyProcessing); } var latestRequest = await _requestRepository.GetLatestAsync(node); var requestedAt = _timestamper.UtcNow; if (!(latestRequest is null) && latestRequest.RequestedAt.Date >= requestedAt.Date) { if (_logger.IsInfo) { _logger.Info($"NDM Faucet request from: {node} was already processed today at: {latestRequest.RequestedAt}."); } return(FaucetResponse.RequestAlreadyProcessedToday(FaucetRequestDetails.From(latestRequest))); } if (!_pendingRequests.TryAdd(node, true)) { if (_logger.IsWarn) { _logger.Warn($"Couldn't start processing NDM Faucet request from: {node}."); } return(FaucetResponse.RequestError); } lock (_locker) { _todayRequestsTotalValueWei += value; if (_logger.IsInfo) { _logger.Info($"Increased NDM Faucet total value of today's ({_today.Date:d}) requests to {_todayRequestsTotalValueWei} wei."); } } if (_todayRequestsTotalValueWei > _dailyRequestsTotalValueWei) { if (_logger.IsInfo) { _logger.Info($"Daily ({_today.Date:d}) requests value for NDM Faucet was reached ({_dailyRequestsTotalValueWei} wei)."); } return(FaucetResponse.DailyRequestsTotalValueReached); } if (_logger.IsInfo) { _logger.Info($"NDM Faucet is processing request for: {node}, address: {address}, value: {value} wei."); } try { var nonce = await _blockchainBridge.GetNonceAsync(_faucetAddress); var transaction = new Transaction { Value = value, GasLimit = Transaction.BaseTxGasCost, GasPrice = 20.GWei(), To = address, SenderAddress = _faucetAddress, Nonce = nonce }; _wallet.Sign(transaction, await _blockchainBridge.GetNetworkIdAsync()); Keccak?transactionHash = await _blockchainBridge.SendOwnTransactionAsync(transaction); if (transactionHash == null) { return(FaucetResponse.ProcessingRequestError); } if (latestRequest is null) { Keccak requestId = Keccak.Compute(Rlp.Encode(Rlp.Encode(node)).Bytes); latestRequest = new EthRequest(requestId, node, address, value, requestedAt, transactionHash); await _requestRepository.AddAsync(latestRequest); } else { latestRequest.UpdateRequestDetails(address, value, requestedAt, transactionHash); await _requestRepository.UpdateAsync(latestRequest); } if (_logger.IsInfo) { _logger.Info($"NDM Faucet has successfully processed request for: {node}, address: {address}, value: {value} wei."); } return(FaucetResponse.RequestCompleted(FaucetRequestDetails.From(latestRequest))); } catch (Exception ex) { if (_logger.IsError) { _logger.Error(ex.Message, ex); } lock (_locker) { _todayRequestsTotalValueWei -= value; if (_logger.IsInfo) { _logger.Info($"Decreased NDM Faucet total value of today's ({_today.Date:d}) requests to {_todayRequestsTotalValueWei} wei."); } } return(FaucetResponse.ProcessingRequestError); } finally { _pendingRequests.TryRemove(node, out _); } }