private static DepositDetails GetDepositDetails(DataAssetUnitType unitType = DataAssetUnitType.Unit, uint confirmationTimestamp = DepositConfirmationTimestamp) => new DepositDetails(new Deposit(Keccak.Zero, 1, 1, 1), GetDataAsset(unitType), TestItem.AddressB, Array.Empty <byte>(), 1, new [] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) }, confirmationTimestamp);
public async Task <RefundClaimStatus> TryClaimEarlyRefundAsync(DepositDetails deposit, Address refundTo) { ulong now = _timestamper.EpochSeconds; if (!deposit.CanClaimEarlyRefund(now, deposit.Timestamp)) { return(RefundClaimStatus.Empty); } Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync(); if (latestBlock == null) { return(RefundClaimStatus.Empty); } now = (ulong)latestBlock.Timestamp; if (!deposit.CanClaimEarlyRefund(now, deposit.Timestamp)) { return(RefundClaimStatus.Empty); } Keccak depositId = deposit.Deposit.Id; Keccak?transactionHash = deposit.ClaimedRefundTransaction?.Hash; if (transactionHash is null) { Address provider = deposit.DataAsset.Provider.Address; if (deposit.EarlyRefundTicket == null) { throw new InvalidDataException($"Early refund ticket is null on a claimable deposit {depositId}"); } EarlyRefundTicket ticket = deposit.EarlyRefundTicket; EarlyRefundClaim earlyRefundClaim = new EarlyRefundClaim(ticket.DepositId, deposit.DataAsset.Id, deposit.Deposit.Units, deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, ticket.ClaimableAfter, ticket.Signature, refundTo); UInt256 gasPrice = await _gasPriceService.GetCurrentRefundAsync(); transactionHash = await _refundService.ClaimEarlyRefundAsync(refundTo, earlyRefundClaim, gasPrice); if (transactionHash is null) { if (_logger.IsError) { _logger.Error("There was an error when trying to claim early refund (no transaction hash returned)."); } return(RefundClaimStatus.Empty); } deposit.AddClaimedRefundTransaction(TransactionInfo.Default(transactionHash, 0, gasPrice, _refundService.GasLimit, _timestamper.EpochSeconds)); await _depositRepository.UpdateAsync(deposit); if (_logger.IsInfo) { _logger.Info($"Claimed an early refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation)."); } } bool confirmed = await TryConfirmClaimAsync(deposit, "early "); return(confirmed ? RefundClaimStatus.Confirmed(transactionHash) : RefundClaimStatus.Unconfirmed(transactionHash)); }
private static DepositDetails GetDepositDetails() => new DepositDetails(new Deposit(Keccak.OfAnEmptyString, 1, 1, 1), GetDataAsset(), TestItem.AddressB, Array.Empty <byte>(), 1, new [] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) }, earlyRefundTicket: new EarlyRefundTicket(Keccak.OfAnEmptyString, 1, null));
public async Task <RefundClaimStatus> TryClaimRefundAsync(DepositDetails deposit, Address refundTo) { ulong now = _timestamper.UnixTime.Seconds; if (!deposit.CanClaimRefund(now)) { DisplayRefundInfo(deposit, now); return(RefundClaimStatus.Empty); } Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync(); if (latestBlock == null) { return(RefundClaimStatus.Empty); } now = (ulong)latestBlock.Timestamp; if (!deposit.CanClaimRefund(now)) { DisplayRefundInfo(deposit, now); return(RefundClaimStatus.Empty); } Keccak depositId = deposit.Deposit.Id; Keccak?transactionHash = deposit.ClaimedRefundTransaction?.Hash; if (transactionHash is null) { Address provider = deposit.DataAsset.Provider.Address; RefundClaim refundClaim = new RefundClaim(depositId, deposit.DataAsset.Id, deposit.Deposit.Units, deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, refundTo); UInt256 gasPrice = await _gasPriceService.GetCurrentRefundGasPriceAsync(); transactionHash = await _refundService.ClaimRefundAsync(refundTo, refundClaim, gasPrice); if (transactionHash is null) { if (_logger.IsError) { _logger.Error("There was an error when trying to claim refund (no transaction hash returned)."); } return(RefundClaimStatus.Empty); } deposit.AddClaimedRefundTransaction(TransactionInfo.Default(transactionHash, 0, gasPrice, _refundService.GasLimit, _timestamper.UnixTime.Seconds)); await _depositRepository.UpdateAsync(deposit); if (_logger.IsInfo) { _logger.Info($"Claimed a refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation)."); } } bool confirmed = await TryConfirmClaimAsync(deposit, string.Empty); return(confirmed ? RefundClaimStatus.Confirmed(transactionHash) : RefundClaimStatus.Unconfirmed(transactionHash)); }
private IEnumerable <PaymentClaim> GetPaymentClaims() { yield return(new PaymentClaim( id: TestItem.KeccakA, depositId: TestItem.KeccakB, assetId: TestItem.KeccakC, assetName: "asset1", units: 1, claimedUnits: 2, unitsRange: new UnitsRange(1, 2), value: 4, claimedValue: 5, expiryTime: 6, pepper: new byte[] { 1, 2, 3 }, provider: TestItem.AddressA, consumer: TestItem.AddressB, signature: new Signature(1, 2, 37), timestamp: 7, transactions: Enumerable.Empty <TransactionInfo>(), status: PaymentClaimStatus.Claimed)); yield return(new PaymentClaim( id: TestItem.KeccakB, depositId: TestItem.KeccakA, assetId: TestItem.KeccakD, assetName: "asset2", units: 1, claimedUnits: 2, unitsRange: new UnitsRange(1, 2), value: 4, claimedValue: 5, expiryTime: 6, pepper: new byte[] { 1, 2, 3 }, provider: TestItem.AddressA, consumer: TestItem.AddressC, signature: new Signature(1, 2, 37), timestamp: 7, transactions: Enumerable.Empty <TransactionInfo>(), status: PaymentClaimStatus.Cancelled)); yield return(new PaymentClaim( id: TestItem.KeccakC, depositId: TestItem.KeccakF, assetId: TestItem.KeccakE, assetName: "asset3", units: 1, claimedUnits: 2, unitsRange: new UnitsRange(1, 2), value: 4, claimedValue: 5, expiryTime: 6, pepper: new byte[] { 1, 2, 3 }, provider: TestItem.AddressA, consumer: TestItem.AddressD, signature: new Signature(1, 2, 37), timestamp: 7, transactions: Enumerable.Empty <TransactionInfo>(), status: PaymentClaimStatus.Sent)); yield return(new PaymentClaim( id: TestItem.KeccakD, depositId: TestItem.KeccakE, assetId: TestItem.KeccakF, assetName: "asset4", units: 1, claimedUnits: 2, unitsRange: new UnitsRange(1, 2), value: 4, claimedValue: 5, expiryTime: 6, pepper: new byte[] { 1, 2, 3 }, provider: TestItem.AddressA, consumer: TestItem.AddressA, signature: new Signature(1, 2, 37), timestamp: 7, transactions: new TransactionInfo[] { TransactionInfo.Default(Keccak.Zero, value: 10, gasPrice: 1, gasLimit: 100, timestamp: 10) }, status: PaymentClaimStatus.Sent)); }
private static DepositDetails GetDepositDetails() => new DepositDetails(new Deposit(Keccak.OfAnEmptyString, 1, DepositExpiryTime, 1), GetDataAsset(), TestItem.AddressB, Array.Empty <byte>(), 1, new[] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) });
public async Task <PaymentClaim?> ProcessAsync(DataDeliveryReceiptRequest receiptRequest, Signature signature) { Keccak depositId = receiptRequest.DepositId; Consumer?consumer = await _consumerRepository.GetAsync(depositId); if (consumer is null) { if (_logger.IsError) { _logger.Error($"Could not find any consumers for deposit {depositId} in the repository."); } return(null); } DataRequest dataRequest = consumer.DataRequest; UnitsRange range = receiptRequest.UnitsRange; uint claimedUnits = range.Units; BigInteger claimedValue = claimedUnits * (BigInteger)consumer.DataRequest.Value / consumer.DataRequest.Units; ulong timestamp = _timestamper.UnixTime.Seconds; Rlp unitsRangeRlp = _unitsRangeRlpDecoder.Encode(range); Keccak id = Keccak.Compute(Rlp.Encode(Rlp.Encode(depositId), Rlp.Encode(timestamp), unitsRangeRlp).Bytes); PaymentClaim paymentClaim = new PaymentClaim(id, consumer.DepositId, consumer.DataAsset.Id, consumer.DataAsset.Name, dataRequest.Units, claimedUnits, range, dataRequest.Value, (UInt256)claimedValue, dataRequest.ExpiryTime, dataRequest.Pepper, dataRequest.Provider, dataRequest.Consumer, signature, timestamp, Array.Empty <TransactionInfo>(), PaymentClaimStatus.Unknown); await _paymentClaimRepository.AddAsync(paymentClaim); if (_logger.IsInfo) { _logger.Info($"Claiming a payment (id: '{paymentClaim.Id}') for deposit: '{depositId}', range: [{range.From}, {range.To}], units: {claimedUnits}."); } UInt256 gasPrice = await _gasPriceService.GetCurrentPaymentClaimGasPriceAsync(); Keccak?transactionHash = null; if (_disableSendingPaymentClaimTransaction) { if (_logger.IsWarn) { _logger.Warn("*** NDM provider sending payment claim transaction is disabled ***"); } } else { transactionHash = await SendTransactionAsync(paymentClaim, gasPrice); if (transactionHash is null) { if (_logger.IsInfo) { _logger.Info($"Payment claim (id: {paymentClaim.Id}) for deposit: '{paymentClaim.DepositId}' did not receive a transaction hash."); } return(paymentClaim); } } if (_logger.IsInfo) { _logger.Info($"Payment claim (id: {paymentClaim.Id}) for deposit: '{paymentClaim.DepositId}' received a transaction hash: '{transactionHash}'."); } paymentClaim.AddTransaction(TransactionInfo.Default(transactionHash, 0, gasPrice, _paymentService.GasLimit, timestamp)); paymentClaim.SetStatus(PaymentClaimStatus.Sent); await _paymentClaimRepository.UpdateAsync(paymentClaim); string claimedEth = ((decimal)claimedValue / Eth).ToString("0.0000"); if (_logger.IsInfo) { _logger.Info($"Sent a payment claim (id: '{paymentClaim.Id}') for deposit: '{depositId}', range: [{range.From}, {range.To}], units: {claimedUnits}, units: {claimedUnits}, value: {claimedValue} wei ({claimedEth} ETH, transaction hash: '{transactionHash}'."); } return(paymentClaim); }
public async Task <Keccak?> MakeAsync(Keccak assetId, uint units, UInt256 value, Address address, UInt256?gasPrice = null) { if (!_wallet.IsUnlocked(address)) { if (_logger.IsWarn) { _logger.Warn($"Account: '{address}' is locked, can't make a deposit."); } return(null); } DataAsset?dataAsset = _dataAssetService.GetDiscovered(assetId); if (dataAsset is null) { if (_logger.IsWarn) { _logger.Warn($"Available data asset: '{assetId}' was not found."); } return(null); } if (!_dataAssetService.IsAvailable(dataAsset)) { if (_logger.IsWarn) { _logger.Warn($"Data asset: '{assetId}' is unavailable, state: {dataAsset.State}."); } return(null); } if (dataAsset.KycRequired && !await _kycVerifier.IsVerifiedAsync(assetId, address)) { return(null); } Address providerAddress = dataAsset.Provider.Address; INdmPeer?provider = _providerService.GetPeer(providerAddress); if (provider is null) { if (_logger.IsWarn) { _logger.Warn($"Provider nodes were not found for address: '{providerAddress}'."); } return(null); } if (dataAsset.MinUnits > units || dataAsset.MaxUnits < units) { if (_logger.IsWarn) { _logger.Warn($"Invalid data request units: '{units}', min: '{dataAsset.MinUnits}', max: '{dataAsset.MaxUnits}'."); } return(null); } UInt256 unitsValue = units * dataAsset.UnitPrice; if (units * dataAsset.UnitPrice != value) { if (_logger.IsWarn) { _logger.Warn($"Invalid data request value: '{value}', while it should be: '{unitsValue}'."); } return(null); } uint now = (uint)_timestamper.EpochSeconds; uint expiryTime = now + (uint)dataAsset.Rules.Expiry.Value; expiryTime += dataAsset.UnitType == DataAssetUnitType.Unit ? 0 : units; byte[] pepper = _cryptoRandom.GenerateRandomBytes(16); byte[] abiHash = _abiEncoder.Encode(AbiEncodingStyle.Packed, _depositAbiSig, assetId.Bytes, units, value, expiryTime, pepper, dataAsset.Provider.Address, address); Keccak depositId = Keccak.Compute(abiHash); Deposit deposit = new Deposit(depositId, units, expiryTime, value); DepositDetails depositDetails = new DepositDetails(deposit, dataAsset, address, pepper, now, Enumerable.Empty <TransactionInfo>(), 0, requiredConfirmations: _requiredBlockConfirmations); UInt256 gasPriceValue = gasPrice is null || gasPrice.Value == 0 ? await _gasPriceService.GetCurrentAsync() : gasPrice.Value; await _depositRepository.AddAsync(depositDetails); Keccak?transactionHash = null; if (_logger.IsInfo) { _logger.Info($"Created a deposit with id: '{depositId}', for data asset: '{assetId}', address: '{address}'."); } if (_disableSendingDepositTransaction) { if (_logger.IsWarn) { _logger.Warn("*** NDM sending deposit transaction is disabled ***"); } } else { transactionHash = await _depositService.MakeDepositAsync(address, deposit, gasPriceValue); } if (transactionHash == null) { if (_logger.IsWarn) { _logger.Warn($"Failed to make a deposit with for data asset: '{assetId}', address: '{address}', gas price: {gasPriceValue} wei."); } return(null); } if (_logger.IsInfo) { _logger.Info($"Sent a deposit with id: '{depositId}', transaction hash: '{transactionHash}' for data asset: '{assetId}', address: '{address}', gas price: {gasPriceValue} wei."); } depositDetails.AddTransaction(TransactionInfo.Default(transactionHash, deposit.Value, gasPriceValue, _depositService.GasLimit, now)); await _depositRepository.UpdateAsync(depositDetails); return(depositId); }
private static DepositDetails GetDepositDetails(uint timestamp = 0, IEnumerable <TransactionInfo> transactions = null) => new DepositDetails(new Deposit(Keccak.Zero, 1, 1, 1), GetDataAsset(DataAssetUnitType.Unit), TestItem.AddressB, Array.Empty <byte>(), 1, transactions ?? new[] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) }, timestamp);
private static DepositDetails GetDepositDetails(uint confirmationTimestamp = 0, uint expiryTime = 1, bool kycRequired = false) => new DepositDetails(new Deposit(Keccak.Zero, 1, expiryTime, 1), GetDataAsset(kycRequired), TestItem.AddressB, Array.Empty <byte>(), 1, new [] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) }, confirmationTimestamp);
private static DepositDetails GetDepositDetails(uint timestamp = 0) => new DepositDetails(new Deposit(TestItem.KeccakA, 1, 1, 1), GetDataAsset(DataAssetUnitType.Unit), TestItem.AddressA, Array.Empty <byte>(), 1, new [] { TransactionInfo.Default(TestItem.KeccakA, 1, 1, 1, 1) }, timestamp);