예제 #1
0
        public async Task Can_make_deposit_with_kyc()
        {
            Address account = _wallet.GetAccounts()[0];

            _kycVerifier.IsVerifiedAsync(null, null).ReturnsForAnyArgs(true);
            Keccak result = await _depositManager.MakeAsync(_withKyc.Id, _withKyc.MinUnits, _withKyc.MinUnits *_withKyc.UnitPrice, account, 20.GWei());

            result.Should().NotBeNull();
        }
예제 #2
0
        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);
        }
예제 #3
0
        public async Task <DataRequestResult> SendAsync(Keccak depositId)
        {
            var deposit = await _depositProvider.GetAsync(depositId);

            if (deposit is null)
            {
                return(DataRequestResult.DepositNotFound);
            }

            if (!_wallet.IsUnlocked(deposit.Consumer))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Account: '{deposit.Consumer}' is locked, can't send a data request.");
                }

                return(DataRequestResult.ConsumerAccountLocked);
            }

            if (deposit.DataAsset.KycRequired &&
                !(await _kycVerifier.IsVerifiedAsync(deposit.DataAsset.Id, deposit.Consumer)))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' has unconfirmed KYC.'");
                }

                return(DataRequestResult.KycUnconfirmed);
            }

            if (!deposit.Confirmed)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' is unconfirmed.'");
                }

                return(DataRequestResult.DepositUnconfirmed);
            }

            if (deposit.IsExpired((uint)_timestamper.EpochSeconds))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' is expired.'");
                }

                return(DataRequestResult.DepositExpired);
            }

            var providerPeer = _providerService.GetPeer(deposit.DataAsset.Provider.Address);

            if (providerPeer is null)
            {
                return(DataRequestResult.ProviderNotFound);
            }

            var sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
            {
                DepositId = depositId,
                Results   = int.MaxValue
            });

            var consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;
            var dataRequest   = CreateDataRequest(deposit);

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending data request for deposit with id: '{depositId}', consumed units: {consumedUnits}, address: '{dataRequest.Consumer}'.");
            }
            var result = await providerPeer.SendDataRequestAsync(dataRequest, consumedUnits);

            if (_logger.IsInfo)
            {
                _logger.Info($"Received data request result: '{result}' for data asset: '{dataRequest.DataAssetId}', deposit: '{depositId}', consumed units: {consumedUnits}, address: '{dataRequest.Consumer}'.");
            }
            await _consumerNotifier.SendDataRequestResultAsync(depositId, result);

            return(result);
        }
예제 #4
0
        public async Task <Keccak> MakeAsync(Keccak assetId, uint units, UInt256 value, Address address)
        {
            if (!_wallet.IsUnlocked(address))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Account: '{address}' is locked, can't make a deposit.");
                }

                return(null);
            }

            var 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);
            }

            var providerAddress = dataAsset.Provider.Address;
            var 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);
            }

            var 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);
            }

            var now        = (uint)_timestamper.EpochSeconds;
            var expiryTime = now + (uint)dataAsset.Rules.Expiry.Value;

            expiryTime += dataAsset.UnitType == DataAssetUnitType.Unit ? 0 : units;
            var pepper  = _cryptoRandom.GenerateRandomBytes(16);
            var abiHash = _abiEncoder.Encode(AbiEncodingStyle.Packed, _depositAbiSig, assetId.Bytes,
                                             units, value, expiryTime, pepper, dataAsset.Provider.Address, address);
            var depositId      = Keccak.Compute(abiHash);
            var deposit        = new Deposit(depositId, units, expiryTime, value);
            var depositDetails = new DepositDetails(deposit, dataAsset, address, pepper, now,
                                                    null, requiredConfirmations: _requiredBlockConfirmations);
            await _depositRepository.AddAsync(depositDetails);

            if (_logger.IsInfo)
            {
                _logger.Info($"Created a deposit with id: '{depositId}', for data asset: '{assetId}', address: '{address}'.");
            }
            var transactionHash = await _depositService.MakeDepositAsync(address, deposit);

            if (_logger.IsInfo)
            {
                _logger.Info($"Sent a deposit with id: '{depositId}', transaction hash: '{transactionHash}' for data asset: '{assetId}', address: '{address}'.");
            }
            depositDetails.SetTransactionHash(transactionHash);
            await _depositRepository.UpdateAsync(depositDetails);

            return(depositId);
        }