Skip to content

Instantly share code, notes, and snippets.

@janus
Created April 3, 2019 09:06
Show Gist options
  • Save janus/9ffb247463eeba62e1d007949f3ddb2d to your computer and use it in GitHub Desktop.
Save janus/9ffb247463eeba62e1d007949f3ddb2d to your computer and use it in GitHub Desktop.
Error and Exception
diff --git a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj
index c095a47..8317fd1 100644
--- a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj
+++ b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj
@@ -72,6 +72,7 @@
<Reference Include="mscorlib" />
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+ <Package>nunit</Package>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
diff --git a/src/GWallet.Backend/Account.fs b/src/GWallet.Backend/Account.fs
index 84e618b..ec303d3 100644
--- a/src/GWallet.Backend/Account.fs
+++ b/src/GWallet.Backend/Account.fs
@@ -139,15 +139,15 @@ module Account =
}
// TODO: add tests for these (just in case address validation breaks after upgrading our dependencies)
- let ValidateAddress (currency: Currency) (address: string): Async<unit> = async {
+ let ValidateAddress (currency: Currency) (address: string) =
if currency.IsEtherBased() then
Ether.Account.ValidateAddress currency address
- do! Ether.Server.CheckIfAddressIsAValidPaymentDestination currency address
+
elif currency.IsUtxo() then
UtxoCoin.Account.ValidateAddress currency address
else
failwith (sprintf "Unknown currency %A" currency)
- }
+
let EstimateFee (account: IAccount) (amount: TransferAmount) destination: Async<IBlockchainFeeInfo> =
@@ -312,9 +312,9 @@ module Account =
raise DestinationEqualToOrigin
let currency = baseAccount.Currency
+ ValidateAddress currency destination
async {
- do! ValidateAddress currency destination
let! txId =
match txMetadata with
@@ -393,9 +393,9 @@ module Account =
File.WriteAllText(filePath, json)
- let CreateReadOnlyAccounts (watchWalletInfo: WatchWalletInfo): Async<unit> = async {
+ let CreateReadOnlyAccounts (watchWalletInfo: WatchWalletInfo) =
for etherCurrency in Currency.GetAll().Where(fun currency -> currency.IsEtherBased()) do
- do! ValidateAddress etherCurrency watchWalletInfo.EtherPublicAddress
+ ValidateAddress etherCurrency watchWalletInfo.EtherPublicAddress
let conceptAccountForReadOnlyAccount = {
Currency = etherCurrency
FileRepresentation = { Name = watchWalletInfo.EtherPublicAddress; Content = fun _ -> String.Empty }
@@ -407,14 +407,14 @@ module Account =
let address =
UtxoCoin.Account.GetPublicAddressFromPublicKey utxoCurrency
(NBitcoin.PubKey(watchWalletInfo.UtxoCoinPublicKey))
- do! ValidateAddress utxoCurrency address
+ ValidateAddress utxoCurrency address
let conceptAccountForReadOnlyAccount = {
Currency = utxoCurrency
FileRepresentation = { Name = address; Content = fun _ -> watchWalletInfo.UtxoCoinPublicKey }
ExtractPublicAddressFromConfigFileFunc = (fun file -> file.Name)
}
Config.AddAccount conceptAccountForReadOnlyAccount AccountKind.ReadOnly |> ignore
- }
+
let Remove (account: ReadOnlyAccount) =
Config.RemoveReadOnlyAccount account
diff --git a/src/GWallet.Backend/Ether/EtherAccount.fs b/src/GWallet.Backend/Ether/EtherAccount.fs
index d8fede4..2bbd7d9 100644
--- a/src/GWallet.Backend/Ether/EtherAccount.fs
+++ b/src/GWallet.Backend/Ether/EtherAccount.fs
@@ -151,6 +151,27 @@ module internal Account =
return gasPrice64
}
+ let EstimateGasCostForContractWithDefaultFunction (account: IAccount) (amount: TransferAmount) destination: Async<TransactionMetadata> = async {
+ let! gasPrice64 = GetGasPrice account.Currency
+
+
+ let! estimateGasForContract = Ether.Server.EstimateGasCostForContract account destination amount.ValueToSend
+ if (estimateGasForContract.Value > BigInteger(Int64.MaxValue)) then
+ failwith (sprintf "GWallet serialization doesn't support such a big integer (%s) for the gas cost of the ton transfer, please report this issue."
+ (estimateGasForContract.Value.ToString()))
+ let gasCost64: Int64 = BigInteger.op_Explicit estimateGasForContract.Value
+
+ let ethMinerFee = MinerFee(gasCost64, gasPrice64, DateTime.Now, account.Currency)
+ let! txCount = GetTransactionCount account.Currency account.PublicAddress
+
+ let feeValue = ethMinerFee.CalculateAbsoluteValue()
+ if (amount.ValueToSend <> amount.BalanceAtTheMomentOfSending &&
+ feeValue > (amount.BalanceAtTheMomentOfSending - amount.ValueToSend)) then
+ raise (InsufficientBalanceForFee feeValue)
+
+ return { Ether.Fee = ethMinerFee; Ether.TransactionCount = txCount }
+ }
+
let private GAS_COST_FOR_A_NORMAL_ETHER_TRANSACTION:int64 = 21000L
let EstimateEtherTransferFee (account: IAccount) (amount: TransferAmount): Async<TransactionMetadata> = async {
@@ -188,7 +209,12 @@ module internal Account =
let EstimateFee (account: IAccount) (amount: TransferAmount) destination: Async<TransactionMetadata> = async {
if account.Currency.IsEther() then
- return! EstimateEtherTransferFee account amount
+ let! isContract = Ether.Server.CheckIfAddressIsAContractAddress account.Currency destination
+ if isContract then
+ return! EstimateGasCostForContractWithDefaultFunction account amount destination
+ else
+ return! EstimateEtherTransferFee account amount
elif account.Currency.IsEthToken() then
return! EstimateTokenTransferFee account amount.ValueToSend destination
else
diff --git a/src/GWallet.Backend/Ether/EtherServer.fs b/src/GWallet.Backend/Ether/EtherServer.fs
index cfa90f1..b76d967 100644
--- a/src/GWallet.Backend/Ether/EtherServer.fs
+++ b/src/GWallet.Backend/Ether/EtherServer.fs
@@ -11,6 +11,7 @@ open Nethereum.Hex.HexTypes
open Nethereum.Web3
open Nethereum.RPC.Eth.DTOs
open Nethereum.StandardTokenEIP20.ContractDefinition
+open Nethereum.RPC.TransactionManagers
open GWallet.Backend
@@ -580,15 +581,41 @@ module Server =
web3Funcs
}
- let CheckIfAddressIsAValidPaymentDestination (currency: Currency) (address: string): Async<unit> =
+ let CheckIfAddressIsAContractAddress (currency: Currency) (address: string): Async<bool> =
async {
let! contractCode = GetContractCode currency address
let emptyContract = "0x"
if not (contractCode.StartsWith emptyContract) then
failwithf "GetCode API should always return a string starting with %s, but got: %s"
- emptyContract contractCode
- elif contractCode <> emptyContract then
- return raise <| InvalidDestinationAddress "Sending to contract addresses is not supported yet. Supply a normal address please."
+ emptyContract contractCode
+
+ return contractCode <> emptyContract
+
+ }
+
+
+ let EstimateGasCostForContract (account: IAccount) destination amount: Async<HexBigInteger> =
+ async {
+
+ let transactionInput = EtherTransferTransactionInputBuilder.CreateTransactionInput(account.PublicAddress, destination, amount)
+ //(string fromAddress, string toAddress, decimal etherAmount, decimal? gasPriceGwei = null, BigInteger? gas = null)
+ let web3Funcs =
+ let web3Func (web3: Web3): Async<HexBigInteger> =
+ let estimateGasJob =
+ async {
+ let task = web3.TransactionManager.EstimateGasAsync(transactionInput)
+ return! Async.AwaitTask task
+ }
+ HandlePossibleEtherFailures estimateGasJob
+ GetWeb3Funcs account.Currency web3Func
+
+ return! faultTolerantEtherClient.Query
+ (FaultTolerantParallelClientDefaultSettings account.Currency Mode.Fast)
+ web3Funcs
+
}
+
+
\ No newline at end of file
diff --git a/src/GWallet.Backend/Exceptions.fs b/src/GWallet.Backend/Exceptions.fs
index 1edf170..5e60e66 100644
--- a/src/GWallet.Backend/Exceptions.fs
+++ b/src/GWallet.Backend/Exceptions.fs
@@ -12,6 +12,3 @@ exception AddressWithInvalidLength of seq<int>
exception AddressWithInvalidChecksum of Option<string>
exception AccountAlreadyAdded
-
-exception InvalidDestinationAddress of msg: string
-
diff --git a/src/GWallet.Frontend.Console/Program.fs b/src/GWallet.Frontend.Console/Program.fs
index 39e61f3..4e130ea 100644
--- a/src/GWallet.Frontend.Console/Program.fs
+++ b/src/GWallet.Frontend.Console/Program.fs
@@ -240,7 +240,6 @@ let rec PerformOptions(numAccounts: int) =
SendPayment()
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
~
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
~
~
~
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
~
~
~
~
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
~
~
~
~
~
~
~
~
(END)
| Options.AddReadonlyAccounts ->
AddReadOnlyAccounts()
- |> Async.RunSynchronously
| Options.SignOffPayment ->
SignOffPayment()
| Options.BroadcastPayment ->
diff --git a/src/GWallet.Frontend.Console/UserInteraction.fs b/src/GWallet.Frontend.Console/UserInteraction.fs
index 50c9fd5..1f0718a 100644
--- a/src/GWallet.Frontend.Console/UserInteraction.fs
+++ b/src/GWallet.Frontend.Console/UserInteraction.fs
@@ -337,12 +337,8 @@ module UserInteraction =
let validatedAddress =
try
Account.ValidateAddress currency publicAddress
- |> Async.RunSynchronously
publicAddress
with
- | InvalidDestinationAddress msg ->
- Presentation.Error msg
- AskPublicAddress currency askText
| AddressMissingProperPrefix(possiblePrefixes) ->
let possiblePrefixesStr = String.Join(", ", possiblePrefixes)
Presentation.Error (sprintf "Address starts with the wrong prefix. Valid prefixes: %s"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment