public async Task <string> SendTransactionAsync(TransactionInput transactionInput) { if (transactionInput == null) { throw new ArgumentNullException(nameof(transactionInput)); } if (string.IsNullOrEmpty(transactionInput.From)) { throw new Exception("From address is null of empty"); } if (string.IsNullOrEmpty(transactionInput.To)) { throw new Exception("Cannot deploy a new contract via the GSN"); } var value = transactionInput.Value.HexValue; if (value != "0" && value != "0x0") { throw new Exception("Cannot send funds via the GSN"); } var relayHubAddress = await _relayHubManager .GetHubAddressAsync(_contractAddress) .ConfigureAwait(false); await ValidateRecipientBalance( relayHubAddress, transactionInput.To, transactionInput.Gas.Value, transactionInput.GasPrice.Value, new BigInteger(0)) .ConfigureAwait(false); var relays = await _relayHubManager .GetRelaysAsync(relayHubAddress, _relayPolicy) .ConfigureAwait(false); foreach (var lazyRelay in relays) { var relay = lazyRelay.Value; if (!relay.Ready || relay.MinGasPrice.CompareTo(transactionInput.GasPrice.Value) == 1) { continue; } try { var hash = await RelayTransaction(relay, transactionInput, relayHubAddress) .ConfigureAwait(false); await _relayPolicy.GraceAsync(relay).ConfigureAwait(false); return(hash); } catch { await _relayPolicy.PenalizeAsync(relay).ConfigureAwait(false); continue; } } return(null); }
public async Task <string> Relay( TransactionInput transaction, Func <Relay, TransactionInput, string, Task <string> > relayFunc) { var relayHubAddress = await _relayHubManager .GetHubAddressAsync(transaction.To) .ConfigureAwait(false); await _balanceValidator.Validate( relayHubAddress, transaction.To, transaction.Gas.Value, transaction.GasPrice.Value, new BigInteger(0)) .ConfigureAwait(false); var relays = await _relayHubManager .GetRelaysAsync(relayHubAddress, _relayPolicy) .ConfigureAwait(false); BigInteger gasPrice = transaction.GasPrice; BigInteger minGasPrice = default; foreach (var lazyRelay in relays) { var relay = lazyRelay.Value; if (minGasPrice == default) { minGasPrice = relay.MinGasPrice; } if (!relay.Ready || relay.MinGasPrice.CompareTo(gasPrice) == 1) { minGasPrice = BigInteger.Min(minGasPrice, relay.MinGasPrice); continue; } try { var nonce = await _relayHubManager .GetNonceAsync(relayHubAddress, transaction.From) .ConfigureAwait(false); transaction.Nonce = new HexBigInteger(nonce); var hash = await relayFunc(relay, transaction, relayHubAddress) .ConfigureAwait(false); await _relayPolicy.GraceAsync(relay).ConfigureAwait(false); return(hash); } catch { await _relayPolicy.PenalizeAsync(relay).ConfigureAwait(false); continue; } } var message = minGasPrice.CompareTo(gasPrice) == 1 ? $"Relay not found. Minimum relay gas price is {minGasPrice}, provided {gasPrice}" : null; throw new GSNRelayNotFoundException(message); }