public async void ShouldSendTransactionWithAccessLists() { var chainId = 444444444500; var accessLists = new List <AccessListItem>(); accessLists.Add(new AccessListItem("0x527306090abaB3A6e1400e9345bC60c78a8BEf57", new List <byte[]> { "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab".HexToByteArray(), "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abac".HexToByteArray() } )); accessLists.Add(new AccessListItem("0x427306090abaB3A6e1400e9345bC60c78a8BEf5c", new List <byte[]> { "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abaa".HexToByteArray(), "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abad".HexToByteArray() } )); var web3 = _ethereumClientIntegrationFixture.GetWeb3(); var nonce = await web3.Eth.TransactionManager.Account.NonceService.GetNextNonceAsync(); var lastBlock = await web3.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync( BlockParameter.CreateLatest()); var baseFee = lastBlock.BaseFeePerGas; var maxPriorityFeePerGas = 2000000000; var maxFeePerGas = baseFee.Value * 2 + 2000000000; var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, 45000, "0x1ad91ee08f21be3de0ba2ba6918e714da6b45836", 10, "", accessLists); transaction1559.Sign(new EthECKey(EthereumClientIntegrationFixture.AccountPrivateKey)); var txnHash = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(transaction1559.GetRLPEncoded() .ToHex()); // create recover signature var txn = await web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txnHash); Assert.True(txn.To.IsTheSameAddress("0x1ad91ee08f21be3de0ba2ba6918e714da6b45836")); Assert.Equal(10, txn.Value.Value); }
public void ShouldEncodeDecodeSignTransaction(ulong chainId, ulong nonce, ulong maxPriorityFeePerGas, ulong maxFeePerGas, ulong gasLimit, string receiverAddress, ulong amount, string data) { var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, receiverAddress, amount, data, null); transaction1559.Sign(new EthECKey("0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7")); var encodedData = transaction1559.GetRLPEncodedRaw(); var signedData = transaction1559.GetRLPEncoded(); Debug.WriteLine(chainId + "," + nonce + "," + maxPriorityFeePerGas + "," + maxFeePerGas + "," + gasLimit + "," + receiverAddress + "," + amount + "," + data); Debug.WriteLine(encodedData.ToHex()); Debug.WriteLine(signedData.ToHex()); var decodedTransaction1559 = Transaction1559Encoder.Current.Decode(signedData); Assert.Equal(transaction1559.Amount, decodedTransaction1559.Amount); Assert.Equal(transaction1559.Nonce, decodedTransaction1559.Nonce); Assert.Equal(transaction1559.ChainId, decodedTransaction1559.ChainId); if (string.IsNullOrEmpty(transaction1559.Data)) { Assert.Null(decodedTransaction1559.Data); } else { Assert.Equal(transaction1559.Data, decodedTransaction1559.Data); } Assert.Equal(transaction1559.GasLimit, decodedTransaction1559.GasLimit); Assert.Equal(transaction1559.MaxFeePerGas, decodedTransaction1559.MaxFeePerGas); Assert.Equal(transaction1559.MaxPriorityFeePerGas, decodedTransaction1559.MaxPriorityFeePerGas); if (string.IsNullOrEmpty(transaction1559.ReceiverAddress)) { Assert.Null(decodedTransaction1559.ReceiverAddress); } else { Assert.Equal(transaction1559.ReceiverAddress, decodedTransaction1559.ReceiverAddress); } Assert.Equal(transaction1559.Signature.V.ToHex(), decodedTransaction1559.Signature.V.ToHex()); Assert.Equal(transaction1559.Signature.R.ToHex(), decodedTransaction1559.Signature.R.ToHex()); Assert.Equal(transaction1559.Signature.S.ToHex(), decodedTransaction1559.Signature.S.ToHex()); Assert.True(decodedTransaction1559.VerifyTransaction()); Assert.True(decodedTransaction1559.GetSenderAddress().IsTheSameAddress("0x12890D2cce102216644c59daE5baed380d84830c")); }
public async void ShouldSendTransactionCalculatingTheDefaultFees() { var chainId = 444444444500; var web3 = _ethereumClientIntegrationFixture.GetWeb3(); var nonce = await web3.Eth.TransactionManager.Account.NonceService.GetNextNonceAsync(); var lastBlock = await web3.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync( BlockParameter.CreateLatest()); var baseFee = lastBlock.BaseFeePerGas; var maxPriorityFeePerGas = 2000000000; var maxFeePerGas = baseFee.Value * 2 + 2000000000; var transaction1559 = new Transaction1559(chainId, nonce.Value, maxPriorityFeePerGas, maxFeePerGas, 45000, "0x1ad91ee08f21be3de0ba2ba6918e714da6b45836", 10, "", null); transaction1559.Sign(new EthECKey(EthereumClientIntegrationFixture.AccountPrivateKey)); var txnHash = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(transaction1559.GetRLPEncoded() .ToHex()); // create recover signature var txn = await web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txnHash); //what I want is to get the right Transaction checking the type or chainid etc and do a recovery Assert.True(txn.To.IsTheSameAddress("0x1ad91ee08f21be3de0ba2ba6918e714da6b45836")); Assert.Equal(10, txn.Value.Value); var transaction1559FromChain = TransactionFactory.CreateTransaction(chainId, (byte)txn.Type.Value, txn.Nonce, txn.MaxPriorityFeePerGas, txn.MaxFeePerGas, null, txn.Gas, txn.To, txn.Value, txn.Input, null, txn.R, txn.S, txn.V); Assert.True(transaction1559FromChain.GetSenderAddress() .IsTheSameAddress("0x12890D2cce102216644c59daE5baed380d84830c")); var transactionReceipt = await new TransactionReceiptPollingService(web3.TransactionManager).PollForReceiptAsync(txnHash, new CancellationTokenSource()); }
public void ShouldEncodeDecodeSignTransactionAccessLists(ulong chainId, ulong nonce, ulong maxPriorityFeePerGas, ulong maxFeePerGas, ulong gasLimit, string receiverAddress, ulong amount, string data) { var accessLists = new List <AccessListItem>(); accessLists.Add(new AccessListItem("0x527306090abaB3A6e1400e9345bC60c78a8BEf57", new List <byte[]> { "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab".HexToByteArray(), "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abac".HexToByteArray() } )); accessLists.Add(new AccessListItem("0x427306090abaB3A6e1400e9345bC60c78a8BEf5c", new List <byte[]> { "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abaa".HexToByteArray(), "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abad".HexToByteArray() } )); var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, receiverAddress, amount, data, accessLists); transaction1559.Sign(new EthECKey("0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7")); var encodedData = transaction1559.GetRLPEncodedRaw(); var signedData = transaction1559.GetRLPEncoded(); Debug.WriteLine(chainId + "," + nonce + "," + maxPriorityFeePerGas + "," + maxFeePerGas + "," + gasLimit + "," + receiverAddress + "," + amount + "," + data); Debug.WriteLine(""); Debug.WriteLine(encodedData.ToHex()); Debug.WriteLine(signedData.ToHex()); var decodedTransaction1559 = Transaction1559Encoder.Current.Decode(signedData); Assert.Equal(transaction1559.Amount, decodedTransaction1559.Amount); Assert.Equal(transaction1559.Nonce, decodedTransaction1559.Nonce); Assert.Equal(transaction1559.ChainId, decodedTransaction1559.ChainId); if (string.IsNullOrEmpty(transaction1559.Data)) { Assert.Null(decodedTransaction1559.Data); } else { Assert.Equal(transaction1559.Data, decodedTransaction1559.Data); } Assert.Equal(transaction1559.GasLimit, decodedTransaction1559.GasLimit); Assert.Equal(transaction1559.MaxFeePerGas, decodedTransaction1559.MaxFeePerGas); Assert.Equal(transaction1559.MaxPriorityFeePerGas, decodedTransaction1559.MaxPriorityFeePerGas); var decodedRlp = decodedTransaction1559.AccessList; Assert.True(accessLists[0].Address.IsTheSameAddress(decodedRlp[0].Address)); Assert.Equal(accessLists[0].StorageKeys[0].ToHex(true), decodedRlp[0].StorageKeys[0].ToHex(true)); Assert.Equal(accessLists[0].StorageKeys[1].ToHex(true), decodedRlp[0].StorageKeys[1].ToHex(true)); Assert.True(accessLists[1].Address.IsTheSameAddress(decodedRlp[1].Address)); Assert.Equal(accessLists[1].StorageKeys[0].ToHex(true), decodedRlp[1].StorageKeys[0].ToHex(true)); Assert.Equal(accessLists[1].StorageKeys[1].ToHex(true), decodedRlp[1].StorageKeys[1].ToHex(true)); if (string.IsNullOrEmpty(transaction1559.ReceiverAddress)) { Assert.Null(decodedTransaction1559.ReceiverAddress); } else { Assert.Equal(transaction1559.ReceiverAddress, decodedTransaction1559.ReceiverAddress); } Assert.Equal(transaction1559.Signature.V.ToHex(), decodedTransaction1559.Signature.V.ToHex()); Assert.Equal(transaction1559.Signature.R.ToHex(), decodedTransaction1559.Signature.R.ToHex()); Assert.Equal(transaction1559.Signature.S.ToHex(), decodedTransaction1559.Signature.S.ToHex()); }
public string SignTransaction(Account account, TransactionInput transaction, BigInteger?overridingAccountChainId = null) { if (transaction == null) { throw new ArgumentNullException(nameof(transaction)); } if (string.IsNullOrWhiteSpace(transaction.From)) { transaction.From = account.Address; } else if (!transaction.From.IsTheSameAddress(account.Address)) { throw new Exception("Invalid account used for signing, does not match the transaction input"); } var chainId = overridingAccountChainId; if (chainId == null) { chainId = account.ChainId; } var nonce = transaction.Nonce; if (nonce == null) { throw new ArgumentNullException(nameof(transaction), "Transaction nonce has not been set"); } var gasLimit = transaction.Gas; var value = transaction.Value ?? new HexBigInteger(0); string signedTransaction; if (transaction.Type != null && transaction.Type.Value == TransactionType.EIP1559.AsByte()) { var maxPriorityFeePerGas = transaction.MaxPriorityFeePerGas.Value; var maxFeePerGas = transaction.MaxFeePerGas.Value; if (chainId == null) { throw new ArgumentException("ChainId required for TransactionType 0X02 EIP1559"); } var transaction1559 = new Transaction1559(chainId.Value, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, transaction.To, value, transaction.Data, transaction.AccessList.ToSignerAccessListItemArray()); transaction1559.Sign(new EthECKey(account.PrivateKey)); signedTransaction = transaction1559.GetRLPEncoded().ToHex(); } else { var gasPrice = transaction.GasPrice; if (chainId == null) { signedTransaction = _legacyTransactionSigner.SignTransaction(account.PrivateKey, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data); } else { signedTransaction = _legacyTransactionSigner.SignTransaction(account.PrivateKey, chainId.Value, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data); } } return(signedTransaction); }
public override Task SignAsync(Transaction1559 transaction) => SignHashTransactionAsync(transaction);
public IEnumerator SignAndSendTransaction(TransactionInput transactionInput) { if (transactionInput == null) { throw new ArgumentNullException("transactionInput"); } if (string.IsNullOrEmpty(transactionInput.From)) { transactionInput.From = _account; } if (!transactionInput.From.IsTheSameAddress(_account)) { throw new Exception("Transaction Input From address does not match private keys address"); } if (transactionInput.Gas == null) { if (EstimateGas) { yield return(_ethEstimateGasUnityRequest.SendRequest(transactionInput)); if (_ethEstimateGasUnityRequest.Exception == null) { var gas = _ethEstimateGasUnityRequest.Result; transactionInput.Gas = gas; } else { this.Exception = _ethEstimateGasUnityRequest.Exception; yield break; } } else { transactionInput.Gas = new HexBigInteger(LegacyTransaction.DEFAULT_GAS_LIMIT); } } if (IsTransactionToBeSendAsEIP1559(transactionInput)) { transactionInput.Type = new HexBigInteger(TransactionType.EIP1559.AsByte()); if (transactionInput.MaxPriorityFeePerGas != null) { if (transactionInput.MaxFeePerGas == null) { yield return(Fee1559SuggestionStrategy.SuggestFee(transactionInput.MaxPriorityFeePerGas.Value)); if (Fee1559SuggestionStrategy.Exception != null) { transactionInput.MaxFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxFeePerGas.Value); } else { this.Exception = Fee1559SuggestionStrategy.Exception; yield break; } } } else { yield return(Fee1559SuggestionStrategy.SuggestFee()); if (Fee1559SuggestionStrategy.Exception != null) { if (transactionInput.MaxFeePerGas == null) { transactionInput.MaxFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxFeePerGas.Value); transactionInput.MaxPriorityFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas.Value); } else { if (transactionInput.MaxFeePerGas < Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas) { transactionInput.MaxPriorityFeePerGas = transactionInput.MaxFeePerGas; } else { transactionInput.MaxPriorityFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas.Value); } } } else { this.Exception = Fee1559SuggestionStrategy.Exception; yield break; } } } else { if (transactionInput.GasPrice == null) { yield return(_ethGasPriceUnityRequest.SendRequest()); if (_ethGasPriceUnityRequest.Exception == null) { var gasPrice = _ethGasPriceUnityRequest.Result; transactionInput.GasPrice = gasPrice; } else { this.Exception = _ethGasPriceUnityRequest.Exception; yield break; } } } var nonce = transactionInput.Nonce; if (nonce == null) { yield return(_transactionCountRequest.SendRequest(_account, Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest())); if (_transactionCountRequest.Exception == null) { nonce = _transactionCountRequest.Result; } else { this.Exception = _transactionCountRequest.Exception; yield break; } } var value = transactionInput.Value; if (value == null) { value = new HexBigInteger(0); } string signedTransaction; if (IsTransactionToBeSendAsEIP1559(transactionInput)) { var transaction1559 = new Transaction1559(_chainId.Value, nonce, transactionInput.MaxPriorityFeePerGas.Value, transactionInput.MaxFeePerGas.Value, transactionInput.Gas.Value, transactionInput.To, value.Value, transactionInput.Data, null); transaction1559.Sign(new EthECKey(_privateKey)); signedTransaction = transaction1559.GetRLPEncoded().ToHex(); } else { if (_chainId == null) { signedTransaction = _transactionSigner.SignTransaction(_privateKey, transactionInput.To, value.Value, nonce, transactionInput.GasPrice.Value, transactionInput.Gas.Value, transactionInput.Data); } else { signedTransaction = _transactionSigner.SignTransaction(_privateKey, _chainId.Value, transactionInput.To, value.Value, nonce, transactionInput.GasPrice.Value, transactionInput.Gas.Value, transactionInput.Data); } } yield return(_ethSendTransactionRequest.SendRequest(signedTransaction)); if (_ethSendTransactionRequest.Exception == null) { this.Result = _ethSendTransactionRequest.Result; } else { this.Exception = _ethSendTransactionRequest.Exception; yield break; } }
public async Task <string> SignTransactionExternallyAsync(TransactionInput transaction) { if (transaction == null) { throw new ArgumentNullException(nameof(transaction)); } if (!transaction.From.IsTheSameAddress(Account.Address)) { throw new Exception("Invalid account used signing"); } SetDefaultGasPriceAndCostIfNotSet(transaction); var nonce = transaction.Nonce; if (nonce == null) { throw new ArgumentNullException(nameof(transaction), "Transaction nonce has not been set"); } var gasPrice = transaction.GasPrice; var gasLimit = transaction.Gas; var value = transaction.Value ?? new HexBigInteger(0); string signedTransaction; var externalSigner = ((ExternalAccount)Account).ExternalSigner; if (externalSigner.Supported1559 && transaction.Type != null && transaction.Type.Value == TransactionType.EIP1559.AsByte()) { var maxPriorityFeePerGas = transaction.MaxPriorityFeePerGas.Value; var maxFeePerGas = transaction.MaxFeePerGas.Value; if (ChainId == null) { throw new ArgumentException("ChainId required for TransactionType 0X02 EIP1559"); } var transaction1559 = new Transaction1559(ChainId.Value, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, transaction.To, value, transaction.Data, transaction.AccessList.ToSignerAccessListItemArray()); await transaction1559.SignExternallyAsync(externalSigner).ConfigureAwait(false); signedTransaction = transaction1559.GetRLPEncoded().ToHex(); } else { if (ChainId == null) { signedTransaction = await _transactionSigner.SignTransactionAsync(externalSigner, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data).ConfigureAwait(false); } else { signedTransaction = await _transactionSigner.SignTransactionAsync(externalSigner, ChainId.Value, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data).ConfigureAwait(false); } } return(signedTransaction); }
public override Task SignAsync(Transaction1559 transaction) { throw new NotSupportedException(); }
public override Task SignAsync(Transaction1559 transaction) { return(SignHashTransactionAsync(transaction)); }