diff --git a/src/GWallet.Backend.Tests/App.config b/src/GWallet.Backend.Tests/App.config new file mode 100644 index 000000000..93f7a1cdf --- /dev/null +++ b/src/GWallet.Backend.Tests/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/GWallet.Backend.Tests/Deserialization.fs b/src/GWallet.Backend.Tests/Deserialization.fs index a7b7866e6..47fe7ad93 100644 --- a/src/GWallet.Backend.Tests/Deserialization.fs +++ b/src/GWallet.Backend.Tests/Deserialization.fs @@ -96,83 +96,71 @@ type Deserialization() = [] member __.``signed btc transaction import``() = - let deserializedSignedTrans: SignedTransaction = + let deserializedSignedTrans: SignedTransaction = Account.ImportSignedTransactionFromJson MarshallingData.SignedBtcTransactionExampleInJson + // Validate deserialized SignedTranasction Assert.That(deserializedSignedTrans, Is.Not.Null) + Assert.That(deserializedSignedTrans.Currency, Is.EqualTo Currency.BTC) + Assert.That(deserializedSignedTrans.FeeCurrency, Is.EqualTo Currency.BTC) Assert.That(deserializedSignedTrans.RawTransaction, - Is.EqualTo "0200000000010111b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4000000001716001427c106013c0042da165c082b3870c31fb3ab4683feffffff0200ca9a3b0000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287873067a3fa0100000017a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d870247304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e8012103fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce5298978c000000") - - Assert.That(deserializedSignedTrans.TransactionInfo, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata, Is.Not.Null) - - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.ValueToSend, - Is.EqualTo(10.01m)) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.BalanceAtTheMomentOfSending, - Is.EqualTo 12.02m) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.Currency, - Is.EqualTo(Currency.BTC)) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.DestinationAddress, - Is.EqualTo("13jxHQDxGto46QhjFiMb78dZdys9ZD8vW5")) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.OriginAddress, - Is.EqualTo("16pKBjGGZkUXo1afyBNf5ttFvV9hauS1kR")) - - let btcTxMetadata = deserializedSignedTrans.TransactionInfo.Metadata :?> UtxoCoin.TransactionMetadata - Assert.That(btcTxMetadata.Fee.EstimatedFeeInSatoshis, Is.EqualTo 10) - Assert.That(btcTxMetadata.Inputs.Length, Is.EqualTo 1) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata.FeeEstimationTime, - Is.EqualTo MarshallingData.SomeDate) - - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.Balances.Count, - Is.EqualTo 5) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.UsdPrice.Count, - Is.EqualTo 5) - + Is.EqualTo "01000000000102cd9e4c06746721fe5d0ecdeabe29a0f05cc22bd7013ff76132efe476d9346bdc0000000017160014618869483590d6c1afe51160f244982e055d213ffdffffffef2763e4690975dc9415d36c06361ddee8393e6d9d86edd748ca21f10788fbc30100000017160014618869483590d6c1afe51160f244982e055d213ffdffffff01ba89000000000000220020574712746ca1942b8f0e3d52e4c1fd9406c3e1b602b328a2a77a57c233fed4640247304402206e9359074007c597a8243d4e5bbfb18ccfd83c0206fcbd1fafc02eb4946852f90220566e0d719b48d11f193d5d6d80eccbaaf44ee1771bf9ea7fd3810d41c5cb429f012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa0247304402202fdbb2ea123c1150b26835ecd54cd59a22bca6a47f32167b35f355fbfcc12d22022011b8314e51b229d6d5a5ee216c9e038b5e05d1b5123485b935a1f823f2bf2279012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa00000000") + + // Can't validate proposal because of "unknown origin account" error + + let btcTxMetadata = + Account.GetTransactionMetadata deserializedSignedTrans + |> Async.RunSynchronously + :?> UtxoCoin.TransactionMetadata + + Assert.That(btcTxMetadata.Fee.EstimatedFeeInSatoshis, Is.EqualTo 980) + Assert.That(btcTxMetadata.Inputs.Length, Is.EqualTo 2) + [] member __.``signed ether transaction import``() = - let deserializedSignedTrans: SignedTransaction = + let deserializedSignedTrans: SignedTransaction = Account.ImportSignedTransactionFromJson MarshallingData.SignedEtherTransactionExampleInJson + // Validate deserialized SignedTransaction Assert.That(deserializedSignedTrans, Is.Not.Null) Assert.That(deserializedSignedTrans.RawTransaction, - Is.EqualTo("doijfsoifjdosisdjfomirmjosmi")) - - Assert.That(deserializedSignedTrans.TransactionInfo, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata, Is.Not.Null) + Is.EqualTo("f86b0185019d334a3482520894d2fdfa29d5ccbb8168ba248d59ded7a25396f84e87022a8ad81f98768026a06bb7c1f8f2b40ed2bc3a3b572cdde7fddb42a8d43c561c60580183b0ed8c2d9fa035183359feab8789642135a253371f80781f4a870f0cae8a7368c5d7e102a688")) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.ValueToSend, - Is.EqualTo(10.01m)) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.BalanceAtTheMomentOfSending, - Is.EqualTo 12.02m) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.Currency, - Is.EqualTo(Currency.ETC)) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.DestinationAddress, - Is.EqualTo("0xf3j4m0rjxdddud9403j")) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.OriginAddress, - Is.EqualTo("0xf3j4m0rjx94sushh03j")) + Assert.That(deserializedSignedTrans.Currency, + Is.EqualTo(Currency.ETH)) + + Assert.That(deserializedSignedTrans.FeeCurrency, + Is.EqualTo(Currency.ETH)) - let etherTxMetadata = deserializedSignedTrans.TransactionInfo.Metadata :?> Ether.TransactionMetadata - Assert.That(etherTxMetadata.TransactionCount, Is.EqualTo(69)) + + // Validate generated proposal + let proposal = Account.GetTransactionProposal deserializedSignedTrans + + Assert.That(proposal.Amount.ValueToSend, + Is.EqualTo(0.000609725773224054m)) + Assert.That(proposal.Amount.Currency, + Is.EqualTo(Currency.ETH)) + Assert.That(proposal.DestinationAddress, + Is.EqualTo("0xd2FDFA29D5ccbb8168Ba248D59dED7a25396f84E")) + Assert.That(proposal.OriginAddress, + Is.EqualTo("0xc295DDB9B89AFb7B0b23cFb76cb34ce33bc854D5")) + + // Validate generated metadata + let etherTxMetadata = + Account.GetTransactionMetadata deserializedSignedTrans + |> Async.RunSynchronously + :?> Ether.TransactionMetadata + + Assert.That(etherTxMetadata.TransactionCount, Is.EqualTo(1)) Assert.That(etherTxMetadata.Fee.Currency, - Is.EqualTo(Currency.ETC)) + Is.EqualTo(Currency.ETH)) Assert.That(etherTxMetadata.Fee.GasPriceInWei, - Is.EqualTo(6969)) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata.FeeEstimationTime, - Is.EqualTo MarshallingData.SomeDate) - - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.Balances.Count, - Is.EqualTo(2)) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.UsdPrice.Count, - Is.EqualTo(2)) + Is.EqualTo(6932351540UL)) [] member __.``unsigned SAI transaction import``() = @@ -205,46 +193,48 @@ type Deserialization() = Assert.That(deserializedUnsignedTrans.Cache.UsdPrice.Count, Is.EqualTo(5)) [] - member __.``signed SAI transaction import``() = + member __.``signed DAI transaction import``() = - let deserializedSignedTrans: SignedTransaction = + let deserializedSignedTrans: SignedTransaction = Account.ImportSignedTransactionFromJson - MarshallingData.SignedSaiTransactionExampleInJson + MarshallingData.SignedDaiTransactionExampleInJson + // Validate deserialized SignedTransaction Assert.That(deserializedSignedTrans, Is.Not.Null) Assert.That(deserializedSignedTrans.RawTransaction, - Is.EqualTo("f8a80784c74d93708291b29489d24a6b4ccb1b6faa2625fe562bdd9a2326035980b844a9059cbb000000000000000000000000db0381b1a380d8db2724a9ca2d33e0c6c044be3b0000000000000000000000000000000000000000000000000de0b6b3a764000026a072cdeb03affd5977c76366efbc1405fbb4fa997ce72c1e4554ba9ec5ef772ddca069d522ea304efebd2537330870bc1ca9e9a6fe3eb5f8d8f66c1b82d9fc27a4bf")) + Is.EqualTo("f8a90185016c653675828792946b175474e89094c44da98b954eedeac495271d0f80b844a9059cbb000000000000000000000000d2fdfa29d5ccbb8168ba248d59ded7a25396f84e0000000000000000000000000000000000000000000000000de0b6b3a764000026a0d5c49133f38f3b60aa41747a4b7cc300a6dac87803b82ba23af9a97fd5994c3ea03122864fd6b294a3da2f3827e70fa861838a168f6533e03587358a6bdc594235")) - Assert.That(deserializedSignedTrans.TransactionInfo, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache, Is.Not.Null) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata, Is.Not.Null) - - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.ValueToSend, - Is.EqualTo(1m)) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.BalanceAtTheMomentOfSending, - Is.EqualTo 7.08m) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.Amount.Currency, - Is.EqualTo Currency.SAI) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.DestinationAddress, - Is.EqualTo("0xDb0381B1a380d8db2724A9Ca2d33E0C6C044bE3b")) - Assert.That(deserializedSignedTrans.TransactionInfo.Proposal.OriginAddress, - Is.EqualTo("0xba766d6d13E2Cc921Bf6e896319D32502af9e37E")) - - let etherTxMetadata = deserializedSignedTrans.TransactionInfo.Metadata :?> Ether.TransactionMetadata - Assert.That(etherTxMetadata.TransactionCount, Is.EqualTo(7)) + Assert.That(deserializedSignedTrans.Currency, + Is.EqualTo Currency.DAI) + + Assert.That(deserializedSignedTrans.FeeCurrency, + Is.EqualTo(Currency.ETH)) + + // Validate generated proposal + let proposal = Account.GetTransactionProposal deserializedSignedTrans + + Assert.That(proposal.Amount.ValueToSend, + Is.EqualTo(1.0m)) + Assert.That(proposal.Amount.Currency, + Is.EqualTo(Currency.DAI)) + Assert.That(proposal.DestinationAddress, + Is.EqualTo("0xd2FDFA29D5ccbb8168Ba248D59dED7a25396f84E")) + Assert.That(proposal.OriginAddress, + Is.EqualTo("0xc295DDB9B89AFb7B0b23cFb76cb34ce33bc854D5")) + + // Validate generated metadata + let etherTxMetadata = + Account.GetTransactionMetadata deserializedSignedTrans + |> Async.RunSynchronously + :?> Ether.TransactionMetadata + + Assert.That(etherTxMetadata.TransactionCount, Is.EqualTo(1)) Assert.That(etherTxMetadata.Fee.Currency, Is.EqualTo(Currency.ETH)) Assert.That(etherTxMetadata.Fee.GasPriceInWei, - Is.EqualTo(3343750000L)) - Assert.That(deserializedSignedTrans.TransactionInfo.Metadata.FeeEstimationTime, - Is.EqualTo MarshallingData.SomeDate) + Is.EqualTo(6113539701UL)) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.Balances.Count, - Is.EqualTo 5) - Assert.That(deserializedSignedTrans.TransactionInfo.Cache.UsdPrice.Count, - Is.EqualTo(5)) [] member __.``can roundtrip currency``() = diff --git a/src/GWallet.Backend.Tests/ElectrumIntegrationTests.fs b/src/GWallet.Backend.Tests/ElectrumIntegrationTests.fs index 696f2a5b5..732325934 100644 --- a/src/GWallet.Backend.Tests/ElectrumIntegrationTests.fs +++ b/src/GWallet.Backend.Tests/ElectrumIntegrationTests.fs @@ -4,6 +4,7 @@ open System open System.Linq open NUnit.Framework +open ElectrumSharp open GWallet.Backend open GWallet.Backend.UtxoCoin @@ -50,7 +51,7 @@ type ElectrumIntegrationTests() = let CheckServerIsReachable (electrumServer: ServerDetails) (currency: Currency) - (query: Async->Async<'T>) + (query: Async->Async<'T>) (assertion: 'T->unit) (maybeFilter: Option bool>) : Async> = async { @@ -61,7 +62,7 @@ type ElectrumIntegrationTests() = // because we want the server incompatibilities to show up here (even if GWallet clients bypass // them in order not to crash) try - let stratumClient = ElectrumClient.StratumServer server + let stratumClient = Electrum.CreateClientFor server let result = query stratumClient |> Async.RunSynchronously @@ -92,7 +93,7 @@ type ElectrumIntegrationTests() = } - let BalanceAssertion (balance: BlockchainScriptHashGetBalanceInnerResult) = + let BalanceAssertion (balance: BlockchainScriptHashGetBalanceResult) = // if these ancient addresses get withdrawals it would be interesting in the crypto space... // so let's make the test check a balance like this which is unlikely to change Assert.That(balance.Confirmed, Is.Not.LessThan 998292) @@ -115,7 +116,7 @@ type ElectrumIntegrationTests() = let TestElectrumServersConnections (electrumServers: seq<_>) currency - (query: Async->Async<'T>) + (query: Async->Async<'T>) (assertion: 'T->unit) (atLeast: uint32) = @@ -157,7 +158,7 @@ type ElectrumIntegrationTests() = (fun server -> rebelBtcServerHostnames.Any(fun rebel -> server.ServerInfo.NetworkPath = rebel)) ElectrumServerSeedList.DefaultBtcList - let UtxosAssertion (utxos: array) = + let UtxosAssertion (utxos: array) = // if these ancient addresses get withdrawals it would be interesting in the crypto space... // so let's make the test check a balance like this which is unlikely to change Assert.That(utxos.Length, Is.GreaterThan 1) @@ -176,21 +177,21 @@ type ElectrumIntegrationTests() = let currency = Currency.BTC let argument = GetScriptHash currency CheckElectrumServersConnection ElectrumServerSeedList.DefaultBtcList currency - (ElectrumClient.GetBalance argument) BalanceAssertion + (Electrum.GetBalance argument) BalanceAssertion [] member __.``can connect (just check balance) to some electrum LTC servers``() = let currency = Currency.LTC let argument = GetScriptHash currency CheckElectrumServersConnection ElectrumServerSeedList.DefaultLtcList currency - (ElectrumClient.GetBalance argument) BalanceAssertion + (Electrum.GetBalance argument) BalanceAssertion [] member __.``can get list UTXOs of an address from some electrum BTC servers``() = let currency = Currency.BTC let argument = GetScriptHash currency CheckElectrumServersConnection btcNonRebelServers currency - (ElectrumClient.GetUnspentTransactionOutputs argument) UtxosAssertion + (Electrum.GetUnspentTransactionOutputs argument) UtxosAssertion [] // to make sure the workaround for https://github.com/nblockchain/JsonRpcSharp/issues/9 works @@ -201,7 +202,7 @@ type ElectrumIntegrationTests() = let argument = "2f309ef555110ab4e9c920faa2d43e64f195aa027e80ec28e1d243bd8929a2fc" CheckElectrumServersConnection btcNonRebelServers currency - (ElectrumClient.GetBlockchainTransaction argument) TxAssertion + (Electrum.GetBlockchainTransaction argument) TxAssertion [] // to make sure the workaround for https://github.com/nblockchain/JsonRpcSharp/issues/9 works @@ -212,5 +213,5 @@ type ElectrumIntegrationTests() = let argument = "2f309ef555110ab4e9c920faa2d43e64f195aa027e80ec28e1d243bd8929a2fc" CheckElectrumServersConnection btcRebelServers currency - (ElectrumClient.GetBlockchainTransaction argument) TxAssertion + (Electrum.GetBlockchainTransaction argument) TxAssertion diff --git a/src/GWallet.Backend.Tests/GWallet.Backend.Tests-legacy.fsproj b/src/GWallet.Backend.Tests/GWallet.Backend.Tests-legacy.fsproj index 7657a1ea9..f41180f84 100644 --- a/src/GWallet.Backend.Tests/GWallet.Backend.Tests-legacy.fsproj +++ b/src/GWallet.Backend.Tests/GWallet.Backend.Tests-legacy.fsproj @@ -9,7 +9,7 @@ GWallet.Backend.Tests GWallet.Backend.Tests v4.7.1 - 4.7.0.0 + 6.0.0.0 true GWallet.Backend.Tests @@ -65,10 +65,9 @@ - - + @@ -109,6 +108,12 @@ ..\..\packages\Fsdk.0.6.0--date20230530-1155.git-3bb8d08\lib\netstandard2.0\Fsdk.dll + + ..\..\packages\ElectrumSharp.0.0.0.2--date20240416-0821.git-3367808\lib\netstandard2.0\ElectrumSharp.dll + + + ..\..\packages\StreamJsonRpc.2.17.11\lib\netstandard2.0\StreamJsonRpc.dll + ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll @@ -124,39 +129,94 @@ ..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net46\System.Security.Cryptography.X509Certificates.dll + + ..\..\packages\System.Text.Json.7.0.3\lib\netstandard2.0\System.Text.Json.dll + - ..\..\packages\FSharp.Core.4.7.0\lib\net45\FSharp.Core.dll + ..\..\packages\FSharp.Core.6.0.1\lib\netstandard2.0\FSharp.Core.dll ..\..\packages\NBitcoin.Altcoins.3.0.8\lib\net452\NBitcoin.Altcoins.dll - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\netstandard2.0\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\..\packages\Microsoft.NET.StringTools.17.4.0\lib\netstandard2.0\Microsoft.NET.StringTools.dll + + + ..\..\packages\Microsoft.VisualStudio.Threading.17.7.35\lib\netstandard2.0\Microsoft.VisualStudio.Threading.dll + + + ..\..\packages\Microsoft.VisualStudio.Threading.Analyzers.17.7.35\lib\netstandard2.0\Microsoft.VisualStudio.Threading.dll + + ..\..\packages\Microsoft.VisualStudio.Validation.17.6.11\lib\netstandard2.0\Microsoft.VisualStudio.Validation.dll + + + ..\..\packages\MessagePack.2.5.108\lib\netstandard2.0\MessagePack.dll + + + ..\..\packages\MessagePack.Annotations.2.5.108\lib\netstandard2.0\MessagePack.Annotations.dll + + + ..\..\packages\Nerdbank.Streams.2.10.69\lib\netstandard2.0\Nerdbank.Streams.dll + ..\..\packages\NBitcoin.6.0.17\lib\net461\NBitcoin.dll ..\..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll + + ..\..\packages\System.Collections.Immutable.7.0.0\lib\netstandard2.0\System.Collections.Immutable.dll + ..\..\packages\System.Linq.4.3.0\lib\net463\System.Linq.dll + + ..\..\packages\System.IO.Pipelines.7.0.0\lib\netstandard2.0\System.IO.Pipelines.dll + ..\..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll + + ..\..\packages\System.Reflection.Emit.4.7.0\lib\netstandard2.0\System.Reflection.Emit.dll + + + ..\..\packages\System.Reflection.Emit.Lightweight.4.7.0\lib\netstandard2.0\System.Reflection.Emit.Lightweight.dll + ..\..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll ..\..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll + + ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll + + + ..\..\packages\System.Threading.Tasks.Dataflow.7.0.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll + + + ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + diff --git a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj index 7407d1b20..1f5479c8e 100644 --- a/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj +++ b/src/GWallet.Backend.Tests/GWallet.Backend.Tests.fsproj @@ -10,7 +10,6 @@ - @@ -51,7 +50,7 @@ - + diff --git a/src/GWallet.Backend.Tests/MarshallingData.fs b/src/GWallet.Backend.Tests/MarshallingData.fs index e8f27c0cf..f717a9a8d 100644 --- a/src/GWallet.Backend.Tests/MarshallingData.fs +++ b/src/GWallet.Backend.Tests/MarshallingData.fs @@ -41,8 +41,8 @@ module MarshallingData = let UnsignedSaiTransactionExampleInJson = ReadEmbeddedResource "unsignedAndFormattedSaiTransaction.json" - let SignedSaiTransactionExampleInJson = - ReadEmbeddedResource "signedAndFormattedSaiTransaction.json" + let SignedDaiTransactionExampleInJson = + ReadEmbeddedResource "signedAndFormattedDaiTransaction.json" let BasicExceptionExampleInJson = ReadEmbeddedResource "basicException.json" @@ -257,8 +257,9 @@ module MarshallingData = let SignedBtcTransactionExample = { - TransactionInfo = UnsignedBtcTransactionExample; - RawTransaction = "0200000000010111b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4000000001716001427c106013c0042da165c082b3870c31fb3ab4683feffffff0200ca9a3b0000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287873067a3fa0100000017a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d870247304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e8012103fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce5298978c000000"; + Currency = Currency.BTC + FeeCurrency = Currency.BTC + RawTransaction = "01000000000102cd9e4c06746721fe5d0ecdeabe29a0f05cc22bd7013ff76132efe476d9346bdc0000000017160014618869483590d6c1afe51160f244982e055d213ffdffffffef2763e4690975dc9415d36c06361ddee8393e6d9d86edd748ca21f10788fbc30100000017160014618869483590d6c1afe51160f244982e055d213ffdffffff01ba89000000000000220020574712746ca1942b8f0e3d52e4c1fd9406c3e1b602b328a2a77a57c233fed4640247304402206e9359074007c597a8243d4e5bbfb18ccfd83c0206fcbd1fafc02eb4946852f90220566e0d719b48d11f193d5d6d80eccbaaf44ee1771bf9ea7fd3810d41c5cb429f012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa0247304402202fdbb2ea123c1150b26835ecd54cd59a22bca6a47f32167b35f355fbfcc12d22022011b8314e51b229d6d5a5ee216c9e038b5e05d1b5123485b935a1f823f2bf2279012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa00000000"; } let SignedBtcTransactionExampleInJson = @@ -303,10 +304,11 @@ module MarshallingData = Cache = realCachingDataExample; Metadata = someSaiTxMetadata } - let SignedSaiTransactionExample = + let SignedDaiTransactionExample = { - TransactionInfo = someSaiTransactionInfo - RawTransaction = "f8a80784c74d93708291b29489d24a6b4ccb1b6faa2625fe562bdd9a2326035980b844a9059cbb000000000000000000000000db0381b1a380d8db2724a9ca2d33e0c6c044be3b0000000000000000000000000000000000000000000000000de0b6b3a764000026a072cdeb03affd5977c76366efbc1405fbb4fa997ce72c1e4554ba9ec5ef772ddca069d522ea304efebd2537330870bc1ca9e9a6fe3eb5f8d8f66c1b82d9fc27a4bf"; + Currency = Currency.DAI + FeeCurrency = Currency.ETH + RawTransaction = "f8a90185016c653675828792946b175474e89094c44da98b954eedeac495271d0f80b844a9059cbb000000000000000000000000d2fdfa29d5ccbb8168ba248d59ded7a25396f84e0000000000000000000000000000000000000000000000000de0b6b3a764000026a0d5c49133f38f3b60aa41747a4b7cc300a6dac87803b82ba23af9a97fd5994c3ea03122864fd6b294a3da2f3827e70fa861838a168f6533e03587358a6bdc594235"; } let someEtherTransactionInfo = @@ -317,8 +319,9 @@ module MarshallingData = } let SignedEtherTransactionExample = { - TransactionInfo = someEtherTransactionInfo; - RawTransaction = "doijfsoifjdosisdjfomirmjosmi"; + Currency = Currency.ETH + FeeCurrency = Currency.ETH + RawTransaction = "f86b0185019d334a3482520894d2fdfa29d5ccbb8168ba248d59ded7a25396f84e87022a8ad81f98768026a06bb7c1f8f2b40ed2bc3a3b572cdde7fddb42a8d43c561c60580183b0ed8c2d9fa035183359feab8789642135a253371f80781f4a870f0cae8a7368c5d7e102a688"; } let SignedEtherTransactionExampleInJson = ReadEmbeddedResource "signedAndFormattedEtherTransaction.json" diff --git a/src/GWallet.Backend.Tests/Serialization.fs b/src/GWallet.Backend.Tests/Serialization.fs index afc048db4..0bbbf4903 100644 --- a/src/GWallet.Backend.Tests/Serialization.fs +++ b/src/GWallet.Backend.Tests/Serialization.fs @@ -76,16 +76,16 @@ type Serialization() = [] member __.``signed SAI transaction export``() = - let json = Account.ExportUnsignedTransactionToJson MarshallingData.SignedSaiTransactionExample + let json = Account.ExportUnsignedTransactionToJson MarshallingData.SignedDaiTransactionExample Assert.That(json, Is.Not.Null) Assert.That(json, Is.Not.Empty) Assert.That(json|> MarshallingData.Sanitize, - Is.EqualTo MarshallingData.SignedSaiTransactionExampleInJson) + Is.EqualTo MarshallingData.SignedDaiTransactionExampleInJson) [] member __.``can serialize exceptions``() = - let json = Account.ExportUnsignedTransactionToJson MarshallingData.SignedSaiTransactionExample + let json = Account.ExportUnsignedTransactionToJson MarshallingData.SignedDaiTransactionExample Assert.That(json, Is.Not.Null) Assert.That(json, Is.Not.Empty) Assert.That(json|> MarshallingData.Sanitize, - Is.EqualTo MarshallingData.SignedSaiTransactionExampleInJson) + Is.EqualTo MarshallingData.SignedDaiTransactionExampleInJson) diff --git a/src/GWallet.Backend.Tests/StratumParsing.fs b/src/GWallet.Backend.Tests/StratumParsing.fs deleted file mode 100644 index 42451ee06..000000000 --- a/src/GWallet.Backend.Tests/StratumParsing.fs +++ /dev/null @@ -1,53 +0,0 @@ -namespace GWallet.Backend.Tests - -open System - -open NUnit.Framework - -open GWallet.Backend -open GWallet.Backend.UtxoCoin - -[] -type StratumParsing() = - - [] - member __.``deserialize a nonJSON response fails with proper exception so that server can be ignored``() = - let errorResponse = String.Empty - - let _ex = Assert.Throws(fun _ -> - StratumClient.Deserialize errorResponse |> ignore - ) - - let errorResponse = "this is not valid json" - - let ex = Assert.Throws(fun _ -> - StratumClient.Deserialize errorResponse |> ignore - ) - Assert.That(ex.Message.Contains errorResponse) - - [] - member __.``deserialize a successful balance response``() = - let balanceResponse = "{\"id\": 1, \"result\": {\"confirmed\": 1, \"unconfirmed\": 2}}" - - let balance = StratumClient.Deserialize balanceResponse - Assert.That(balance.Result.Confirmed, Is.EqualTo(1)) - Assert.That(balance.Result.Unconfirmed, Is.EqualTo(2)) - - [] - member __.``deserialize a stratum error from an electrum client doesn't fail``() = - let errorResponse = "{\"jsonrpc\": \"2.0\", \"id\": 0, \"error\": {\"message\": \"internal error processing request\", \"code\": -32603}}" - - let ex = Assert.Throws(fun _ -> - StratumClient.Deserialize errorResponse - |> ignore - ) - Assert.That(ex.ErrorCode, Is.EqualTo(Some -32603)) - - [] - member __.``can deserialize error result with string error``() = - let ex = Assert.Throws (fun () -> - StratumClient.Deserialize """{"error":"bad tx_hash","id":0,"jsonrpc":"2.0"}""" - |> ignore - ) - - Assert.That(ex.ErrorCode, Is.EqualTo None) diff --git a/src/GWallet.Backend.Tests/data/signedAndFormattedBtcTransaction.json b/src/GWallet.Backend.Tests/data/signedAndFormattedBtcTransaction.json index d9ad44b3a..e74a38405 100644 --- a/src/GWallet.Backend.Tests/data/signedAndFormattedBtcTransaction.json +++ b/src/GWallet.Backend.Tests/data/signedAndFormattedBtcTransaction.json @@ -1,66 +1,13 @@ { "Version": "{version}", - "TypeName": "GWallet.Backend.SignedTransaction`1[[GWallet.Backend.UtxoCoin.TransactionMetadata, GWallet.Backend, Version={version}, Culture=neutral, PublicKeyToken=null]]", + "TypeName": "GWallet.Backend.SignedTransaction", "Value": { - "TransactionInfo": { - "Proposal": { - "OriginAddress": "16pKBjGGZkUXo1afyBNf5ttFvV9hauS1kR", - "Amount": { - "ValueToSend": 10.01, - "BalanceAtTheMomentOfSending": 12.02, - "Currency": { - "Case": "BTC" - } - }, - "DestinationAddress": "13jxHQDxGto46QhjFiMb78dZdys9ZD8vW5" - }, - "Metadata": { - "Fee": { - "EstimatedFeeInSatoshis": 10, - "EstimationTime": "2018-06-14T16:50:09.133411Z", - "Currency": { - "Case": "BTC" - } - }, - "Inputs": [ - { - "TransactionHash": "4d129e98d87fab00a99ebc88688752b588ec7d38c2ba5dc86d3563a6bc4c691f", - "OutputIndex": 1, - "ValueInSatoshis": 1000, - "DestinationInHex": "a9145131075257d8b8de8298e7c52891eb4b87823b9387" - } - ] - }, - "Cache": { - "UsdPrice": { - "BTC": 9156.19, - "ETC": 19.8644, - "ETH": 691.52, - "LTC": 173.592, - "SAI": 1.00376 - }, - "Addresses": { - "0xba766d6d13E2Cc921Bf6e896319D32502af9e37E": [ - "ETH", - "SAI", - "ETC" - ], - "3Buz1evVsQeHtDfQAmwfAKQsUzAt3f4TuR": [ - "BTC" - ], - "MJ88KYLTpXVigiwJGevzyxfGogmKx7WiWm": [ - "LTC" - ] - }, - "Balances": { - "BTC": 0.0, - "ETC": 8.0, - "ETH": 7.08, - "LTC": 0.0, - "SAI": 1.0 - } - } + "FeeCurrency": { + "Case": "BTC" }, - "RawTransaction": "0200000000010111b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4000000001716001427c106013c0042da165c082b3870c31fb3ab4683feffffff0200ca9a3b0000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287873067a3fa0100000017a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d870247304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e8012103fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce5298978c000000" + "Currency": { + "Case": "BTC" + }, + "RawTransaction": "01000000000102cd9e4c06746721fe5d0ecdeabe29a0f05cc22bd7013ff76132efe476d9346bdc0000000017160014618869483590d6c1afe51160f244982e055d213ffdffffffef2763e4690975dc9415d36c06361ddee8393e6d9d86edd748ca21f10788fbc30100000017160014618869483590d6c1afe51160f244982e055d213ffdffffff01ba89000000000000220020574712746ca1942b8f0e3d52e4c1fd9406c3e1b602b328a2a77a57c233fed4640247304402206e9359074007c597a8243d4e5bbfb18ccfd83c0206fcbd1fafc02eb4946852f90220566e0d719b48d11f193d5d6d80eccbaaf44ee1771bf9ea7fd3810d41c5cb429f012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa0247304402202fdbb2ea123c1150b26835ecd54cd59a22bca6a47f32167b35f355fbfcc12d22022011b8314e51b229d6d5a5ee216c9e038b5e05d1b5123485b935a1f823f2bf2279012102b7326aff8f2e56a341c31fbf50d0ce1a641859d837daffd7bf03f1f80a8c5eaa00000000" } } diff --git a/src/GWallet.Backend.Tests/data/signedAndFormattedDaiTransaction.json b/src/GWallet.Backend.Tests/data/signedAndFormattedDaiTransaction.json new file mode 100644 index 000000000..cf73e51dc --- /dev/null +++ b/src/GWallet.Backend.Tests/data/signedAndFormattedDaiTransaction.json @@ -0,0 +1,13 @@ +{ + "Version": "{version}", + "TypeName": "GWallet.Backend.SignedTransaction", + "Value": { + "FeeCurrency": { + "Case": "ETH" + }, + "Currency": { + "Case": "DAI" + }, + "RawTransaction": "f8a90185016c653675828792946b175474e89094c44da98b954eedeac495271d0f80b844a9059cbb000000000000000000000000d2fdfa29d5ccbb8168ba248d59ded7a25396f84e0000000000000000000000000000000000000000000000000de0b6b3a764000026a0d5c49133f38f3b60aa41747a4b7cc300a6dac87803b82ba23af9a97fd5994c3ea03122864fd6b294a3da2f3827e70fa861838a168f6533e03587358a6bdc594235" + } +} diff --git a/src/GWallet.Backend.Tests/data/signedAndFormattedEtherTransaction.json b/src/GWallet.Backend.Tests/data/signedAndFormattedEtherTransaction.json index 401148db1..cde673821 100644 --- a/src/GWallet.Backend.Tests/data/signedAndFormattedEtherTransaction.json +++ b/src/GWallet.Backend.Tests/data/signedAndFormattedEtherTransaction.json @@ -1,49 +1,13 @@ { "Version": "{version}", - "TypeName": "GWallet.Backend.SignedTransaction`1[[GWallet.Backend.Ether.TransactionMetadata, GWallet.Backend, Version={version}, Culture=neutral, PublicKeyToken=null]]", + "TypeName": "GWallet.Backend.SignedTransaction", "Value": { - "TransactionInfo": { - "Proposal": { - "OriginAddress": "0xf3j4m0rjx94sushh03j", - "Amount": { - "ValueToSend": 10.01, - "BalanceAtTheMomentOfSending": 12.02, - "Currency": { - "Case": "ETC" - } - }, - "DestinationAddress": "0xf3j4m0rjxdddud9403j" - }, - "Metadata": { - "Fee": { - "GasLimit": 21000, - "GasPriceInWei": 6969, - "Currency": { - "Case": "ETC" - }, - "EstimationTime": "2018-06-14T16:50:09.133411Z" - }, - "TransactionCount": 69 - }, - "Cache": { - "UsdPrice": { - "ETC": 169.99999999, - "ETH": 161.796 - }, - "Addresses": { - "0xFOOBARBAZ": [ - "ETC" - ], - "1fooBarBaz": [ - "BTC" - ] - }, - "Balances": { - "BTC": 0.0, - "ETC": 123456789.12345678 - } - } + "FeeCurrency": { + "Case": "ETH" }, - "RawTransaction": "doijfsoifjdosisdjfomirmjosmi" + "Currency": { + "Case": "ETH" + }, + "RawTransaction": "f86b0185019d334a3482520894d2fdfa29d5ccbb8168ba248d59ded7a25396f84e87022a8ad81f98768026a06bb7c1f8f2b40ed2bc3a3b572cdde7fddb42a8d43c561c60580183b0ed8c2d9fa035183359feab8789642135a253371f80781f4a870f0cae8a7368c5d7e102a688" } } diff --git a/src/GWallet.Backend.Tests/data/signedAndFormattedSaiTransaction.json b/src/GWallet.Backend.Tests/data/signedAndFormattedSaiTransaction.json deleted file mode 100644 index 0dd6bfab1..000000000 --- a/src/GWallet.Backend.Tests/data/signedAndFormattedSaiTransaction.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "Version": "{version}", - "TypeName": "GWallet.Backend.SignedTransaction`1[[GWallet.Backend.Ether.TransactionMetadata, GWallet.Backend, Version={version}, Culture=neutral, PublicKeyToken=null]]", - "Value": { - "TransactionInfo": { - "Proposal": { - "OriginAddress": "0xba766d6d13E2Cc921Bf6e896319D32502af9e37E", - "Amount": { - "ValueToSend": 1.0, - "BalanceAtTheMomentOfSending": 7.08, - "Currency": { - "Case": "SAI" - } - }, - "DestinationAddress": "0xDb0381B1a380d8db2724A9Ca2d33E0C6C044bE3b" - }, - "Metadata": { - "Fee": { - "GasLimit": 37298, - "GasPriceInWei": 3343750000, - "Currency": { - "Case": "ETH" - }, - "EstimationTime": "2018-06-14T16:50:09.133411Z" - }, - "TransactionCount": 7 - }, - "Cache": { - "UsdPrice": { - "BTC": 9156.19, - "ETC": 19.8644, - "ETH": 691.52, - "LTC": 173.592, - "SAI": 1.00376 - }, - "Addresses": { - "0xba766d6d13E2Cc921Bf6e896319D32502af9e37E": [ - "ETH", - "SAI", - "ETC" - ], - "3Buz1evVsQeHtDfQAmwfAKQsUzAt3f4TuR": [ - "BTC" - ], - "MJ88KYLTpXVigiwJGevzyxfGogmKx7WiWm": [ - "LTC" - ] - }, - "Balances": { - "BTC": 0.0, - "ETC": 8.0, - "ETH": 7.08, - "LTC": 0.0, - "SAI": 1.0 - } - } - }, - "RawTransaction": "f8a80784c74d93708291b29489d24a6b4ccb1b6faa2625fe562bdd9a2326035980b844a9059cbb000000000000000000000000db0381b1a380d8db2724a9ca2d33e0c6c044be3b0000000000000000000000000000000000000000000000000de0b6b3a764000026a072cdeb03affd5977c76366efbc1405fbb4fa997ce72c1e4554ba9ec5ef772ddca069d522ea304efebd2537330870bc1ca9e9a6fe3eb5f8d8f66c1b82d9fc27a4bf" - } -} diff --git a/src/GWallet.Backend.Tests/packages.config b/src/GWallet.Backend.Tests/packages.config index db38c0fe3..3fd9ba9e0 100644 --- a/src/GWallet.Backend.Tests/packages.config +++ b/src/GWallet.Backend.Tests/packages.config @@ -1,28 +1,49 @@  - + + + - + + + + + + + + + + + + + + + + + + + + diff --git a/src/GWallet.Backend/Account.fs b/src/GWallet.Backend/Account.fs index a2b006f1a..e53216d25 100644 --- a/src/GWallet.Backend/Account.fs +++ b/src/GWallet.Backend/Account.fs @@ -229,13 +229,32 @@ module Account = | _ -> () } + + let GetTransactionProposal (signedTransaction: SignedTransaction) = + if signedTransaction.Currency.IsUtxo() then + UtxoCoin.Account.GetSignedTransactionProposal signedTransaction + elif signedTransaction.Currency.IsEtherBased() then + Ether.Account.GetSignedTransactionProposal signedTransaction + else + failwith "Unknown currency type for parsing proposal from raw transaction" + + let GetTransactionMetadata (signedTransaction: SignedTransaction) = + if signedTransaction.Currency.IsUtxo() then + UtxoCoin.Account.GetTransactionFeeMetadata signedTransaction + elif signedTransaction.Currency.IsEtherBased() then + async { + return Ether.Account.GetTransactionFeeMetadata signedTransaction + } + else + failwith "Unknown currency type for parsing metadata from raw transaction" + // FIXME: broadcasting shouldn't just get N consistent replies from FaultTolerantClient, // but send it to as many as possible, otherwise it could happen that some server doesn't // broadcast it even if you sent it - let BroadcastTransaction (trans: SignedTransaction<_>) (ignoreHigherMinerFeeThanAmount: bool): Async = + let BroadcastTransaction (trans: SignedTransaction) (ignoreHigherMinerFeeThanAmount: bool): Async = async { - let currency = trans.TransactionInfo.Proposal.Amount.Currency + let currency = trans.Currency let! txId = if currency.IsEtherBased() then @@ -245,9 +264,11 @@ module Account = else failwith <| SPrintF1 "Unknown currency %A" currency - do! CheckIfOutOfGas trans.TransactionInfo.Metadata txId + let! txMetadata = GetTransactionMetadata trans + + do! CheckIfOutOfGas txMetadata txId - SaveOutgoingTransactionInCache trans.TransactionInfo.Proposal trans.TransactionInfo.Metadata txId + SaveOutgoingTransactionInCache (GetTransactionProposal trans) txMetadata txId let uri = BlockExplorer.GetTransaction currency txId return uri @@ -404,7 +425,7 @@ module Account = async { do! ValidateAddress currency destination - let! txId = + let! txId, txRawTransaction = match txMetadata with | :? UtxoCoin.TransactionMetadata as btcTxMetadata -> if not (currency.IsUtxo()) then @@ -423,6 +444,15 @@ module Account = | _ -> failwith "Unknown tx metadata type" + let signedTransaction = + { + SignedTransaction.FeeCurrency = txMetadata.Currency + Currency = currency + RawTransaction = txRawTransaction + } + + let! txMetadata = GetTransactionMetadata signedTransaction + do! CheckIfOutOfGas txMetadata txId let transactionProposal = @@ -447,40 +477,19 @@ module Account = unsignedTrans.Metadata password - { TransactionInfo = unsignedTrans; RawTransaction = rawTransaction } + { + FeeCurrency = unsignedTrans.Metadata.Currency + Currency = unsignedTrans.Proposal.Amount.Currency + RawTransaction = rawTransaction + } - let private ExportSignedTransaction (trans: SignedTransaction<_>) = + let private ExportSignedTransaction (trans: SignedTransaction) = Marshalling.Serialize trans - let private SerializeSignedTransactionPlain (trans: SignedTransaction<_>): string = - let json = - match trans.TransactionInfo.Metadata.GetType() with - | t when t = typeof -> - let unsignedEthTx = { - Metadata = box trans.TransactionInfo.Metadata :?> Ether.TransactionMetadata; - Proposal = trans.TransactionInfo.Proposal; - Cache = trans.TransactionInfo.Cache; - } - let signedEthTx = { - TransactionInfo = unsignedEthTx; - RawTransaction = trans.RawTransaction; - } - ExportSignedTransaction signedEthTx - | t when t = typeof -> - let unsignedBtcTx = { - Metadata = box trans.TransactionInfo.Metadata :?> UtxoCoin.TransactionMetadata; - Proposal = trans.TransactionInfo.Proposal; - Cache = trans.TransactionInfo.Cache; - } - let signedBtcTx = { - TransactionInfo = unsignedBtcTx; - RawTransaction = trans.RawTransaction; - } - ExportSignedTransaction signedBtcTx - | _ -> failwith "Unknown miner fee type" - json + let private SerializeSignedTransactionPlain (trans: SignedTransaction): string = + ExportSignedTransaction trans - let SerializeSignedTransaction (transaction: SignedTransaction<_>) + let SerializeSignedTransaction (transaction: SignedTransaction) (compressed: bool) : string = @@ -490,7 +499,7 @@ module Account = else Marshalling.Compress json - let SaveSignedTransaction (trans: SignedTransaction<_>) (filePath: string) = + let SaveSignedTransaction (trans: SignedTransaction) (filePath: string) = let json = SerializeSignedTransaction trans false File.WriteAllText(filePath, json) @@ -696,12 +705,12 @@ module Account = let deserializedBtcTransaction: UnsignedTransaction = Marshalling.Deserialize json deserializedBtcTransaction.ToAbstract() - | _ when transType.GetGenericTypeDefinition() = typedefof> -> + | _ when transType.GetGenericTypeDefinition() = typedefof -> raise TransactionAlreadySigned | unexpectedType -> raise <| Exception(SPrintF1 "Unknown unsignedTransaction subtype: %s" unexpectedType.FullName) - let public ImportSignedTransactionFromJson (jsonOrCompressedJson: string): SignedTransaction = + let public ImportSignedTransactionFromJson (jsonOrCompressedJson: string): SignedTransaction = let json = try @@ -713,14 +722,8 @@ module Account = let transType = Marshalling.ExtractType json match transType with - | _ when transType = typeof> -> - let deserializedBtcTransaction: SignedTransaction = - Marshalling.Deserialize json - deserializedBtcTransaction.ToAbstract() - | _ when transType = typeof> -> - let deserializedBtcTransaction: SignedTransaction = - Marshalling.Deserialize json - deserializedBtcTransaction.ToAbstract() + | _ when transType = typeof -> + Marshalling.Deserialize json | _ when transType.GetGenericTypeDefinition() = typedefof> -> raise TransactionNotSignedYet | unexpectedType -> @@ -746,14 +749,9 @@ module Account = let deserializedTransaction: UnsignedTransaction = Marshalling.Deserialize json Unsigned(deserializedTransaction.ToAbstract()) - | _ when transType = typeof> -> - let deserializedTransaction: SignedTransaction = - Marshalling.Deserialize json - Signed(deserializedTransaction.ToAbstract()) - | _ when transType = typeof> -> - let deserializedTransaction: SignedTransaction = - Marshalling.Deserialize json - Signed(deserializedTransaction.ToAbstract()) + | _ when transType = typeof -> + Marshalling.Deserialize json + |> Signed | unexpectedType -> failwith <| SPrintF1 "Unknown unsignedTransaction subtype: %s" unexpectedType.FullName @@ -768,16 +766,14 @@ module Account = ImportUnsignedTransactionFromJson unsignedTransInJson - let GetSignedTransactionDetails<'T when 'T :> IBlockchainFeeInfo> (signedTransaction: SignedTransaction<'T>) + let GetSignedTransactionDetails (signedTransaction: SignedTransaction) : ITransactionDetails = - let currency = signedTransaction.TransactionInfo.Proposal.Amount.Currency + let currency = signedTransaction.Currency if currency.IsUtxo () then UtxoCoin.Account.GetSignedTransactionDetails - signedTransaction.RawTransaction - currency + signedTransaction elif currency.IsEtherBased () then Ether.Account.GetSignedTransactionDetails signedTransaction else failwith <| (SPrintF1 "Unknown currency: %A" currency) - diff --git a/src/GWallet.Backend/Ether/EtherAccount.fs b/src/GWallet.Backend/Ether/EtherAccount.fs index ec4fe860c..b7d75353e 100644 --- a/src/GWallet.Backend/Ether/EtherAccount.fs +++ b/src/GWallet.Backend/Ether/EtherAccount.fs @@ -8,6 +8,7 @@ open System.Numerics open System.Threading.Tasks open Nethereum.ABI.Decoders +open Nethereum.Model open Nethereum.Signer open Nethereum.KeyStore open Nethereum.Util @@ -20,7 +21,7 @@ open GWallet.Backend.FSharpUtil.UwpHacks module internal Account = let private addressUtil = AddressUtil() - let private signer = TransactionSigner() + let private signer = LegacyTransactionSigner() let private KeyStoreService = KeyStoreService() @@ -236,7 +237,7 @@ module internal Account = let private ValidateMinerFee (trans: string) = let intDecoder = IntTypeDecoder() - let tx = TransactionFactory.CreateTransaction trans + let tx = TransactionFactory.CreateTransaction trans :?> SignedLegacyTransaction let amountInWei = intDecoder.DecodeBigInteger tx.Value @@ -254,9 +255,9 @@ module internal Account = ValidateMinerFee trans Ether.Server.BroadcastTransaction currency ("0x" + trans) - let BroadcastTransaction (trans: SignedTransaction<_>) = + let BroadcastTransaction (trans: SignedTransaction) = BroadcastRawTransaction - trans.TransactionInfo.Proposal.Amount.Currency + trans.Currency trans.RawTransaction let internal GetPrivateKey (account: NormalAccount) password = @@ -365,8 +366,7 @@ module internal Account = else failwith <| SPrintF1 "Assertion failed: Ether currency %A not supported?" account.Currency - let chain = GetNetwork account.Currency - if not (signer.VerifyTransaction(trans, chain)) then + if not (TransactionVerificationAndRecovery.VerifyTransaction trans) then failwith "Transaction could not be verified?" trans @@ -401,15 +401,19 @@ module internal Account = (amount: TransferAmount) (password: string) (ignoreHigherMinerFeeThanAmount: bool) = - let baseAccount = account :> IAccount - if (baseAccount.PublicAddress.Equals(destination, StringComparison.InvariantCultureIgnoreCase)) then - raise DestinationEqualToOrigin + async { + let baseAccount = account :> IAccount + if (baseAccount.PublicAddress.Equals(destination, StringComparison.InvariantCultureIgnoreCase)) then + raise DestinationEqualToOrigin + + let currency = baseAccount.Currency - let currency = baseAccount.Currency + let trans = SignTransaction account txMetadata destination amount password - let trans = SignTransaction account txMetadata destination amount password + let! txId = BroadcastRawTransaction currency trans ignoreHigherMinerFeeThanAmount - BroadcastRawTransaction currency trans ignoreHigherMinerFeeThanAmount + return txId, trans + } let private CreateInternal (password: string) (seed: array): FileRepresentation = let privateKey = EthECKey(seed, true) @@ -449,47 +453,71 @@ module internal Account = } ExportUnsignedTransactionToJson unsignedTransaction + let GetTransactionFeeMetadata (signedTransaction: SignedTransaction): IBlockchainFeeInfo = + let intDecoder = IntTypeDecoder() + let parsedTx = TransactionFactory.CreateTransaction signedTransaction.RawTransaction :?> SignedLegacyTransaction + let gasLimitInWei = intDecoder.DecodeBigInteger parsedTx.GasLimit |> int64 + let gasPriceInWei = intDecoder.DecodeBigInteger parsedTx.GasPrice |> int64 + let nonce = intDecoder.DecodeBigInteger parsedTx.Nonce |> int64 - let GetSignedTransactionDetails (signedTransaction: SignedTransaction<'T>): ITransactionDetails = - - match signedTransaction.TransactionInfo.Proposal.Amount.Currency with - | SAI | DAI -> - // FIXME: derive the transaction details from the raw transaction so that we can remove the proposal from - // the SignedTransaction type (as it's redundant); and when we remove it, we can also rename - // IBlockchainFeeInfo's Currency to "FeeCurrency", or change "Metadata" members whose type is - // IBlockchainFeeInfo to have "fee" in the name too, otherwise is to easy to use ETH instead of DAI - signedTransaction.TransactionInfo.Proposal :> ITransactionDetails - - | _ -> - let getTransactionChainId (tx: TransactionBase) = - // the chain id can be deconstructed like so - - // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md - // into one of the following - - // https://chainid.network/ - // NOTE: according to the SO discussion, the following alrogithm is adequate - - // https://stackoverflow.com/questions/68023440/how-do-i-use-nethereum-to-extract-chain-id-from-a-raw-transaction - let v = IntTypeDecoder().DecodeBigInteger tx.Signature.V - let chainId = (v - BigInteger 35) / BigInteger 2 - chainId - - let getTransactionCurrency (tx: TransactionBase) = - match int (getTransactionChainId tx) with - | chainId when chainId = int Config.EthNet -> ETH - | chainId when chainId = int Config.EtcNet -> ETC - | other -> failwith <| SPrintF1 "Could not infer currency from transaction where chainId = %i." other - - let tx = TransactionFactory.CreateTransaction signedTransaction.RawTransaction - - // HACK: I prefix 12 elements to the address due to AddressTypeDecoder expecting some sort of header... - let address = AddressTypeDecoder().Decode (Array.append (Array.zeroCreate 12) tx.ReceiveAddress) - - let destAddress = addressUtil.ConvertToChecksumAddress address - + { + TransactionMetadata.Fee = + MinerFee(gasLimitInWei, gasPriceInWei, DateTime.Now, signedTransaction.FeeCurrency) + TransactionCount = nonce + } :> IBlockchainFeeInfo + + let GetSignedTransactionDetails (signedTransaction: SignedTransaction): ITransactionDetails = + let getTransactionChainId (tx: SignedLegacyTransactionBase) = + // the chain id can be deconstructed like so - + // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md + // into one of the following - + // https://chainid.network/ + // NOTE: according to the SO discussion, the following alrogithm is adequate - + // https://stackoverflow.com/questions/68023440/how-do-i-use-nethereum-to-extract-chain-id-from-a-raw-transaction + let v = IntTypeDecoder().DecodeBigInteger tx.Signature.V + let chainId = (v - BigInteger 35) / BigInteger 2 + chainId + + let getTransactionCurrency (tx: SignedLegacyTransactionBase) = + match int (getTransactionChainId tx) with + | chainId when chainId = int Config.EthNet -> ETH + | chainId when chainId = int Config.EtcNet -> ETC + | other -> failwith <| SPrintF1 "Could not infer currency from transaction where chainId = %i." other + + let tx = TransactionFactory.CreateTransaction signedTransaction.RawTransaction :?> SignedLegacyTransaction + + let destAddress = tx.ReceiveAddress.ConvertToEthereumChecksumAddress() + + match TokenManager.TryGetCurrencyByContractAddress destAddress with + | None -> let txDetails = { - OriginAddress = signer.GetSenderAddress signedTransaction.RawTransaction + OriginAddress = TransactionVerificationAndRecovery.GetSenderAddress signedTransaction.RawTransaction Amount = UnitConversion.Convert.FromWei (IntTypeDecoder().DecodeBigInteger tx.Value) Currency = getTransactionCurrency tx DestinationAddress = destAddress } txDetails :> ITransactionDetails + | Some tokenCurrency -> + let tokenServiceWrapper = + TokenManager.OfflineTokenServiceWrapper tokenCurrency + + let destinationAddress, amountInWei = + tokenServiceWrapper.DecodeInputDataForTransferTransaction tx.Data + + let txDetails = + { + OriginAddress = TransactionVerificationAndRecovery.GetSenderAddress signedTransaction.RawTransaction + Amount = UnitConversion.Convert.FromWei amountInWei + Currency = tokenCurrency + DestinationAddress = destinationAddress + } + txDetails :> ITransactionDetails + let GetSignedTransactionProposal (signedTx: SignedTransaction): UnsignedTransactionProposal = + let txDetail = GetSignedTransactionDetails signedTx + { + UnsignedTransactionProposal.Amount = + TransferAmount(txDetail.Amount, txDetail.Amount, txDetail.Currency) + OriginAddress = txDetail.OriginAddress + DestinationAddress = txDetail.DestinationAddress + } \ No newline at end of file diff --git a/src/GWallet.Backend/Ether/EtherExceptions.fs b/src/GWallet.Backend/Ether/EtherExceptions.fs index 7bb36b17f..c02143e84 100644 --- a/src/GWallet.Backend/Ether/EtherExceptions.fs +++ b/src/GWallet.Backend/Ether/EtherExceptions.fs @@ -94,3 +94,13 @@ type UnhandledWebException = } new (info: SerializationInfo, context: StreamingContext) = { inherit Exception (info, context) } + +type ProtocolGlitchException = + inherit CommunicationUnsuccessfulException + + new (message) = { inherit CommunicationUnsuccessfulException (message) } + new (message: string, innerException: Exception) = { + inherit CommunicationUnsuccessfulException (message, innerException) + } + new (info: SerializationInfo, context: StreamingContext) = + { inherit CommunicationUnsuccessfulException (info, context) } diff --git a/src/GWallet.Backend/Ether/EtherServer.fs b/src/GWallet.Backend/Ether/EtherServer.fs index e755a1bb3..b80fcda66 100644 --- a/src/GWallet.Backend/Ether/EtherServer.fs +++ b/src/GWallet.Backend/Ether/EtherServer.fs @@ -8,6 +8,7 @@ open System.Linq open Nethereum.Util open Nethereum.Hex.HexTypes +open Nethereum.JsonRpc.Client open Nethereum.Web3 open Nethereum.RPC.Eth.DTOs open Nethereum.StandardTokenEIP20.ContractDefinition @@ -20,8 +21,8 @@ type BalanceType = | Unconfirmed | Confirmed -type SomeWeb3 (connectionTimeOut, url: string) = - inherit Web3 (connectionTimeOut, url) +type SomeWeb3 (url: string) = + inherit Web3 (url) member val Url = url with get @@ -67,7 +68,7 @@ module Web3ServerSeedList = module Server = - let private Web3Server (connectionTimeOut, serverDetails: ServerDetails) = + let private Web3Server (serverDetails: ServerDetails) = match serverDetails.ServerInfo.ConnectionType with | { Protocol = Tcp _ ; Encrypted = _ } -> failwith <| SPrintF1 "Ether server of TCP connection type?: %s" serverDetails.ServerInfo.NetworkPath @@ -78,7 +79,7 @@ module Server = else "http" let uri = SPrintF2 "%s://%s" protocol serverDetails.ServerInfo.NetworkPath - SomeWeb3 (connectionTimeOut, uri) + SomeWeb3 uri let HttpRequestExceptionMatchesErrorCode (ex: Http.HttpRequestException) (errorCode: int): bool = ex.Message.StartsWith(SPrintF1 "%i " errorCode) || ex.Message.Contains(SPrintF1 " %i " errorCode) @@ -200,7 +201,7 @@ module Server = ] let MaybeRethrowRpcResponseException (ex: Exception): unit = - let maybeRpcResponseEx = FSharpUtil.FindException ex + let maybeRpcResponseEx = FSharpUtil.FindException ex match maybeRpcResponseEx with | Some rpcResponseEx -> if not (isNull rpcResponseEx.RpcError) then @@ -243,7 +244,7 @@ module Server = let MaybeRethrowRpcClientTimeoutException (ex: Exception): unit = let maybeRpcTimeoutException = - FSharpUtil.FindException ex + FSharpUtil.FindException ex match maybeRpcTimeoutException with | Some rpcTimeoutEx -> raise <| ServerTimedOutException(exMsg, rpcTimeoutEx) @@ -260,7 +261,7 @@ module Server = // this could be a Xamarin.Android bug (see https://gitlab.com/nblockchain/geewallet/issues/119) let MaybeRethrowObjectDisposedException (ex: Exception): unit = - let maybeRpcUnknownEx = FSharpUtil.FindException ex + let maybeRpcUnknownEx = FSharpUtil.FindException ex match maybeRpcUnknownEx with | Some _ -> let maybeObjectDisposedEx = FSharpUtil.FindException ex @@ -274,12 +275,12 @@ module Server = () let MaybeRethrowInnerRpcException (ex: Exception): unit = - let maybeRpcUnknownEx = FSharpUtil.FindException ex + let maybeRpcUnknownEx = FSharpUtil.FindException ex match maybeRpcUnknownEx with | Some rpcUnknownEx -> let maybeDeSerializationEx = - FSharpUtil.FindException rpcUnknownEx + FSharpUtil.FindException rpcUnknownEx match maybeDeSerializationEx with | None -> () @@ -340,11 +341,9 @@ module Server = | ServerSelectionMode.Fast -> 3u | ServerSelectionMode.Analysis -> 2u - let etcEcosystemIsMomentarilyCentralized = false - let private FaultTolerantParallelClientInnerSettings (numberOfConsistentResponsesRequired: uint32) (mode: ServerSelectionMode) - currency + _currency maybeConsistencyConfig = let consistencyConfig = @@ -352,10 +351,7 @@ module Server = | None -> SpecificNumberOfConsistentResponsesRequired numberOfConsistentResponsesRequired | Some specificConsistencyConfig -> specificConsistencyConfig - let retries = - match currency with - | Currency.ETC when etcEcosystemIsMomentarilyCentralized -> Config.NUMBER_OF_RETRIES_TO_SAME_SERVERS * 2u - | _ -> Config.NUMBER_OF_RETRIES_TO_SAME_SERVERS + let retries = Config.NUMBER_OF_RETRIES_TO_SAME_SERVERS { NumberOfParallelJobsAllowed = NumberOfParallelJobsForMode mode @@ -377,11 +373,7 @@ module Server = } let private FaultTolerantParallelClientDefaultSettings (mode: ServerSelectionMode) (currency: Currency) = - let numberOfConsistentResponsesRequired = - if etcEcosystemIsMomentarilyCentralized && currency = Currency.ETC then - 1u - else - 2u + let numberOfConsistentResponsesRequired = 2u FaultTolerantParallelClientInnerSettings numberOfConsistentResponsesRequired mode currency @@ -390,9 +382,7 @@ module Server = (currency: Currency) (cacheOrInitialBalanceMatchFunc: decimal->bool) = let consistencyConfig = - if etcEcosystemIsMomentarilyCentralized && currency = Currency.ETC then - None - elif mode = ServerSelectionMode.Fast then + if mode = ServerSelectionMode.Fast then Some (OneServerConsistentWithCertainValueOrTwoServers cacheOrInitialBalanceMatchFunc) else None @@ -407,7 +397,7 @@ module Server = let Web3ServerToRetrievalFunc (server: ServerDetails) (web3ClientFunc: SomeWeb3->Async<'R>) - currency + _currency : Async<'R> = let HandlePossibleEtherFailures (job: Async<'R>): Async<'R> = @@ -422,15 +412,10 @@ module Server = return raise <| FSharpUtil.ReRaise ex } - let connectionTimeout = - match currency with - | Currency.ETC when etcEcosystemIsMomentarilyCentralized -> - Config.DEFAULT_NETWORK_TIMEOUT + Config.DEFAULT_NETWORK_TIMEOUT - | _ -> - Config.DEFAULT_NETWORK_TIMEOUT + ClientBase.ConnectionTimeout <- Config.DEFAULT_NETWORK_TIMEOUT async { - let web3Server = Web3Server (connectionTimeout, server) + let web3Server = Web3Server (server) try return! HandlePossibleEtherFailures (web3ClientFunc web3Server) @@ -678,11 +663,7 @@ module Server = return hexBigInteger } GetRandomizedFuncs currency web3Func - let minResponsesRequired = - if etcEcosystemIsMomentarilyCentralized && currency = Currency.ETC then - 1u - else - 2u + let minResponsesRequired = 2u return! faultTolerantEtherClient.Query (FaultTolerantParallelClientDefaultSettings ServerSelectionMode.Fast @@ -712,7 +693,7 @@ module Server = web3Funcs with | ex -> - match FSharpUtil.FindException ex with + match FSharpUtil.FindException ex with | None -> return raise (FSharpUtil.ReRaise ex) | Some rpcResponseException -> diff --git a/src/GWallet.Backend/Ether/TokenManager.fs b/src/GWallet.Backend/Ether/TokenManager.fs index ed00b7f22..c627f5157 100644 --- a/src/GWallet.Backend/Ether/TokenManager.fs +++ b/src/GWallet.Backend/Ether/TokenManager.fs @@ -4,6 +4,7 @@ open System.Numerics open Nethereum.Web3 open Nethereum.Hex.HexTypes +open Nethereum.Hex.HexConvertors.Extensions open Nethereum.StandardTokenEIP20 open Nethereum.StandardTokenEIP20.ContractDefinition @@ -12,10 +13,20 @@ open GWallet.Backend.FSharpUtil.UwpHacks module TokenManager = + let ContractAddresses: Map = + Map [ + Currency.DAI, "0x6B175474E89094C44Da98b954EedeAC495271d0F" + Currency.SAI, "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359" + ] + + let TryGetCurrencyByContractAddress addr = + ContractAddresses + |> Map.tryFindKey (fun _currency contractAddress -> contractAddress = addr) + let GetTokenContractAddress currency = match currency with - | Currency.DAI -> "0x6B175474E89094C44Da98b954EedeAC495271d0F" - | Currency.SAI -> "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359" + | Currency.DAI + | Currency.SAI -> ContractAddresses.[currency] | _ -> raise <| invalidOp (SPrintF1 "%A has no contract address" currency) type TokenServiceWrapper(web3, currency: Currency) = @@ -45,8 +56,28 @@ module TokenManager = failwith "Assertion failed: transactionInput's VALUE property should be equal to passed tokenAmountInWei parameter" transactionInput.Data + member self.DecodeInputDataForTransferTransaction (data: byte[]) = + let transferFuncBuilder = self.ContractHandler.GetFunction() + let decodedInput = transferFuncBuilder.DecodeInput (data.ToHex true) + + let expectedParamsCount = 2 + + let transferDestination, transferAmountInWei = + try + if decodedInput.Count = expectedParamsCount then + decodedInput.[0].Result :?> string, + decodedInput.[1].Result :?> BigInteger + else + failwith <| SPrintF2 "Invalid transfer function parameters count, expected %i got %i" expectedParamsCount decodedInput.Count + with + | :? System.InvalidCastException -> + failwith "Invalid transfer function parameters type" + + transferDestination, transferAmountInWei + + // this is a dummy instance we need in order to pass it to base class of StandardTokenService, but not // really used online; FIXME: propose "Web3-less" overload to Nethereum - let private dummyOfflineWeb3 = Web3 Config.DEFAULT_NETWORK_TIMEOUT + let private dummyOfflineWeb3 = Web3() type OfflineTokenServiceWrapper(currency: Currency) = inherit TokenServiceWrapper(dummyOfflineWeb3, currency) diff --git a/src/GWallet.Backend/GWallet.Backend-legacy.fsproj b/src/GWallet.Backend/GWallet.Backend-legacy.fsproj index dc11f1779..5ab5a4a65 100644 --- a/src/GWallet.Backend/GWallet.Backend-legacy.fsproj +++ b/src/GWallet.Backend/GWallet.Backend-legacy.fsproj @@ -9,7 +9,7 @@ GWallet.Backend GWallet.Backend v4.7.1 - 4.7.0.0 + 6.0.0.0 true GWallet.Backend @@ -60,7 +60,6 @@ - @@ -71,7 +70,6 @@ - @@ -95,6 +93,9 @@ ..\..\packages\Fsdk.0.6.0--date20230530-1155.git-3bb8d08\lib\netstandard2.0\Fsdk.dll + + ..\..\packages\ElectrumSharp.0.0.0.2--date20240416-0821.git-3367808\lib\netstandard2.0\ElectrumSharp.dll + ..\..\packages\FSharp.Data.3.0.0\lib\net45\FSharp.Data.dll @@ -190,14 +191,14 @@ ..\..\packages\NBitcoin.6.0.17\lib\net461\NBitcoin.dll - ..\..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll - ..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard1.3\System.IO.Pipelines.dll + ..\..\packages\System.IO.Pipelines.7.0.0\lib\netstandard2.0\System.IO.Pipelines.dll - ..\..\packages\FSharp.Core.4.7.0\lib\net45\FSharp.Core.dll + ..\..\packages\FSharp.Core.6.0.1\lib\netstandard2.0\FSharp.Core.dll ..\..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll @@ -236,10 +237,7 @@ - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll - - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.TcpClient.dll + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll ..\..\packages\System.IO.Pipes.4.3.0\lib\net46\System.IO.Pipes.dll @@ -250,50 +248,59 @@ ..\..\packages\System.Net.WebSockets.Client.4.3.2\lib\net46\System.Net.WebSockets.Client.dll - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.Client.dll + + ..\..\packages\ADRaffy.ENSNormalize.0.1.5\lib\net461\ADRaffy.ENSNormalize.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.BlockchainProcessing.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.Client.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.RpcClient.dll - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.IpcClient.dll + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Merkle.Patricia.dll - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.HttpClient.dll + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Model.dll - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.WebSocketClient.dll + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.EIP712.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.ABI.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.ABI.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Accounts.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Accounts.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Contracts.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Contracts.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Hex.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Hex.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.KeyStore.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.KeyStore.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RLP.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RLP.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RPC.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RPC.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Signer.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Util.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Util.dll - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Web3.dll + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Web3.dll ..\..\packages\HtmlAgilityPack.1.11.24\lib\Net45\HtmlAgilityPack.dll @@ -303,7 +310,7 @@ - ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll ..\..\packages\DotNetEssentials.1.6.1--date20220823-0234.git-14ad2d3\lib\netstandard2.0\Xamarin.Essentials.dll @@ -315,4 +322,5 @@ --> + diff --git a/src/GWallet.Backend/GWallet.Backend.fsproj b/src/GWallet.Backend/GWallet.Backend.fsproj index e1bdf08ff..3825ab9a8 100644 --- a/src/GWallet.Backend/GWallet.Backend.fsproj +++ b/src/GWallet.Backend/GWallet.Backend.fsproj @@ -23,7 +23,6 @@ - @@ -34,7 +33,6 @@ - @@ -58,7 +56,10 @@ - + + + + @@ -69,7 +70,7 @@ - + diff --git a/src/GWallet.Backend/JsonRpcTcpClient.fs b/src/GWallet.Backend/JsonRpcTcpClient.fs deleted file mode 100644 index 9069a1065..000000000 --- a/src/GWallet.Backend/JsonRpcTcpClient.fs +++ /dev/null @@ -1,110 +0,0 @@ -namespace GWallet.Backend - -open System -open System.Net -open System.Net.Sockets -open System.Runtime.Serialization - -open Fsdk - -open GWallet.Backend.FSharpUtil.UwpHacks - -type ProtocolGlitchException = - inherit CommunicationUnsuccessfulException - - new (message) = { inherit CommunicationUnsuccessfulException (message) } - new (message: string, innerException: Exception) = { - inherit CommunicationUnsuccessfulException (message, innerException) - } - new (info: SerializationInfo, context: StreamingContext) = - { inherit CommunicationUnsuccessfulException (info, context) } - -type ServerCannotBeResolvedException = - inherit CommunicationUnsuccessfulException - - new(message) = { inherit CommunicationUnsuccessfulException(message) } - new(message:string, innerException: Exception) = { inherit CommunicationUnsuccessfulException(message, innerException) } - new (info: SerializationInfo, context: StreamingContext) = - { inherit CommunicationUnsuccessfulException (info, context) } - -type ServerNameResolvedToInvalidAddressException = - inherit CommunicationUnsuccessfulException - - new (message) = { inherit CommunicationUnsuccessfulException (message) } - new (info: SerializationInfo, context: StreamingContext) = - { inherit CommunicationUnsuccessfulException (info, context) } - - -type JsonRpcTcpClient (host: string, port: uint32) = - - let ResolveAsync (hostName: string): Async> = async { - // FIXME: loop over all addresses? - let! hostEntry = Dns.GetHostEntryAsync hostName |> Async.AwaitTask - return hostEntry.AddressList |> Array.tryHead - } - - let exceptionMsg = "JsonRpcSharp faced some problem when trying communication" - - let ResolveHost(): Async = async { - try - let! maybeTimedOutipAddress = ResolveAsync host |> FSharpUtil.WithTimeout Config.DEFAULT_NETWORK_TIMEOUT - match maybeTimedOutipAddress with - | Some ipAddressOption -> - match ipAddressOption with - | Some ipAddress -> - if ipAddress.ToString().StartsWith("127.0.0.") then - let msg = SPrintF2 "Server '%s' resolved to localhost IP '%s'" host (ipAddress.ToString()) - return raise <| ServerNameResolvedToInvalidAddressException (msg) - else - return ipAddress - | None -> return raise <| ServerCannotBeResolvedException - (SPrintF1 "DNS host entry lookup resulted in no records for %s" host) - | None -> return raise <| TimeoutException (SPrintF2 "Timed out connecting to %s:%i" host port) - with - | :? TimeoutException -> - return raise(ServerCannotBeResolvedException(exceptionMsg)) - | ex -> - match FSharpUtil.FindException ex with - | None -> - return raise <| FSharpUtil.ReRaise ex - | Some socketException -> - if socketException.ErrorCode = int SocketError.HostNotFound || - socketException.ErrorCode = int SocketError.NoData || - socketException.ErrorCode = int SocketError.TryAgain then - return raise <| ServerCannotBeResolvedException(exceptionMsg, ex) - return raise <| UnhandledSocketException(socketException.ErrorCode, ex) - } - - let rpcTcpClientInnerRequest = - let tcpClient = - JsonRpcSharp.TcpClient.JsonRpcClient(ResolveHost, int port, Config.DEFAULT_NETWORK_CONNECT_TIMEOUT) - fun jsonRequest -> tcpClient.RequestAsync jsonRequest - - member __.Host with get() = host - - member __.Request (request: string): Async = async { - try - let! stringOption = rpcTcpClientInnerRequest request |> FSharpUtil.WithTimeout Config.DEFAULT_NETWORK_TIMEOUT - let str = - match stringOption with - | Some s -> s - | None -> raise <| ServerTimedOutException("Timeout when trying to communicate with UtxoCoin server") - return str - with - | :? CommunicationUnsuccessfulException as ex -> - return raise <| FSharpUtil.ReRaise ex - | :? JsonRpcSharp.TcpClient.CommunicationUnsuccessfulException as ex -> - return raise <| CommunicationUnsuccessfulException(ex.Message, ex) - - // FIXME: we should log this one on Sentry as a warning because it's really strange, I bet it's a bug - // on Mono that could maybe go away with higher versions of it (higher versions of Xamarin-Android), see - // git blame to look at the whole stacktrace (ex.ToString()) - | :? NotSupportedException as nse -> - return raise <| ProtocolGlitchException(exceptionMsg, nse) - | ex -> - match Networking.FindExceptionToRethrow ex exceptionMsg with - | None -> - return raise <| FSharpUtil.ReRaise ex - | Some rewrappedSocketException -> - return raise rewrappedSocketException - } diff --git a/src/GWallet.Backend/ServerManager.fs b/src/GWallet.Backend/ServerManager.fs index dbe42a612..8e89c1ac4 100644 --- a/src/GWallet.Backend/ServerManager.fs +++ b/src/GWallet.Backend/ServerManager.fs @@ -117,8 +117,15 @@ module ServerManager = failwith <| SPrintF1 "Currency %A not UTXO?" currency let utxoFunc electrumServer = async { - let! bal = UtxoCoin.ElectrumClient.GetBalance scriptHash electrumServer - return bal.Confirmed |> decimal + try + let! bal = UtxoCoin.Electrum.GetBalance scriptHash electrumServer + return bal.Confirmed |> decimal + with + | ex -> + match Fsdk.FSharpUtil.FindException ex with + | Some commFailedExn -> + return raise <| CommunicationUnsuccessfulException(commFailedExn.Message, commFailedExn) + | None -> return raise ex } UtxoCoin.Server.GetServerFuncs utxoFunc servers |> Some diff --git a/src/GWallet.Backend/Transaction.fs b/src/GWallet.Backend/Transaction.fs index 6f1764e69..b20670a83 100644 --- a/src/GWallet.Backend/Transaction.fs +++ b/src/GWallet.Backend/Transaction.fs @@ -46,17 +46,13 @@ type UnsignedTransaction<'T when 'T:> IBlockchainFeeInfo> = Proposal = self.Proposal; } -type SignedTransaction<'T when 'T:> IBlockchainFeeInfo> = +type SignedTransaction = { - TransactionInfo: UnsignedTransaction<'T>; - RawTransaction: string; + FeeCurrency: Currency + Currency: Currency + RawTransaction: string } - member self.ToAbstract(): SignedTransaction = - { - TransactionInfo = self.TransactionInfo.ToAbstract(); - RawTransaction = self.RawTransaction; - } type ImportedTransaction<'T when 'T:> IBlockchainFeeInfo> = | Unsigned of UnsignedTransaction<'T> -| Signed of SignedTransaction<'T> +| Signed of SignedTransaction diff --git a/src/GWallet.Backend/UtxoCoin/ElectrumClient.fs b/src/GWallet.Backend/UtxoCoin/ElectrumClient.fs index 594725962..3ad0de02e 100644 --- a/src/GWallet.Backend/UtxoCoin/ElectrumClient.fs +++ b/src/GWallet.Backend/UtxoCoin/ElectrumClient.fs @@ -2,114 +2,26 @@ open System -open GWallet.Backend -open GWallet.Backend.FSharpUtil.UwpHacks - -module ElectrumClient = - - let private Init (fqdn: string) (port: uint32): Async = - let jsonRpcClient = new JsonRpcTcpClient(fqdn, port) - let stratumClient = new StratumClient(jsonRpcClient) - - // this is the last version of Electrum released at the time of writing this module - let CLIENT_NAME_SENT_TO_STRATUM_SERVER_WHEN_HELLO = "geewallet" +open ElectrumSharp - // last version of the protocol [1] as of electrum's source code [2] at the time of - // writing this... actually this changes relatively rarely (one of the last changes - // was for 2.4 version [3] (changes documented here[4]) - // [1] https://electrumx-spesmilo.readthedocs.io/en/latest/protocol.html - // [2] https://github.com/spesmilo/electrum/blob/master/lib/version.py - // [3] https://github.com/spesmilo/electrum/commit/118052d81597eff3eb636d242eacdd0437dabdd6 - // [4] https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-changes.html - let PROTOCOL_VERSION_SUPPORTED = Version "1.4" - - async { - let! versionSupportedByServer = - try - stratumClient.ServerVersion CLIENT_NAME_SENT_TO_STRATUM_SERVER_WHEN_HELLO PROTOCOL_VERSION_SUPPORTED - with - | :? ElectrumServerReturningErrorException as ex -> - if (ex.ErrorCode = Some 1 && ex.Message.StartsWith "unsupported protocol version" && - ex.Message.EndsWith (PROTOCOL_VERSION_SUPPORTED.ToString())) then - - // FIXME: even if this ex is already handled to ignore the server, we should report to sentry as WARN - raise <| ServerTooNewException(SPrintF1 "Version of server rejects our client version (%s)" - (PROTOCOL_VERSION_SUPPORTED.ToString())) - else - reraise() - if versionSupportedByServer < PROTOCOL_VERSION_SUPPORTED then - raise (ServerTooOldException (SPrintF2 "Version of server is older (%s) than the client (%s)" - (versionSupportedByServer.ToString()) - (PROTOCOL_VERSION_SUPPORTED.ToString()))) - return stratumClient - } +open GWallet.Backend - let StratumServer (electrumServer: ServerDetails): Async = +module Electrum = + let CreateClientFor (electrumServer: ServerDetails): Async = match electrumServer.ServerInfo.ConnectionType with | { Encrypted = true; Protocol = _ } -> failwith "Incompatibility filter for non-encryption didn't work?" | { Encrypted = false; Protocol = Http } -> failwith "HTTP server for UtxoCoin?" | { Encrypted = false; Protocol = Tcp port } -> - Init electrumServer.ServerInfo.NetworkPath port - - let GetBalance (scriptHash: string) (stratumServer: Async) = async { - // FIXME: we should rather implement this method in terms of: - // - querying all unspent transaction outputs (X) -> block heights included - // - querying transaction history (Y) -> block heights included - // - check the difference between X and Y (e.g. Y - X = Z) - // - query details of each element in Z to see their block heights - // - query the current blockheight (H) -> pick the highest among all servers queried - // -> having H, we now know which elements of X, Y, and Z are confirmed or not - // Doing it this way has two advantages: - // 1) We can configure GWallet with a number of confirmations to consider some balance confirmed (instead - // of trusting what "confirmed" means from the point of view of the Electrum Server) - // 2) and most importantly: we could verify each of the transactions supplied in X, Y, Z to verify their - // integrity (in a similar fashion as Electrum Wallet client already does), to not have to trust servers* - // [ see https://www.youtube.com/watch?v=hjYCXOyDy7Y&feature=youtu.be&t=1171 for more information ] - // * -> although that would be fixing only half of the problem, we also need proof of completeness - let! stratumClient = stratumServer - let! balanceResult = stratumClient.BlockchainScriptHashGetBalance scriptHash - return balanceResult.Result - } - - let GetUnspentTransactionOutputs scriptHash (stratumServer: Async) = async { - let! stratumClient = stratumServer - let! unspentListResult = stratumClient.BlockchainScriptHashListUnspent scriptHash - return unspentListResult.Result - } - - let GetBlockchainTransaction txHash (stratumServer: Async) = async { - let! stratumClient = stratumServer - let! blockchainTransactionResult = stratumClient.BlockchainTransactionGet txHash - return blockchainTransactionResult.Result - } - - // DON'T DELETE, used in external projects - let GetBlockchainTransactionIdFromPos (height: UInt32) (txPos: UInt32) (stratumServer: Async) = async { - let! stratumClient = stratumServer - let! blockchainTransactionResult = stratumClient.BlockchainTransactionIdFromPos height txPos - return blockchainTransactionResult.Result - } - - let EstimateFee (numBlocksTarget: int) (stratumServer: Async): Async = async { - let! stratumClient = stratumServer - let! estimateFeeResult = stratumClient.BlockchainEstimateFee numBlocksTarget - if estimateFeeResult.Result = -1m then - return raise <| ServerMisconfiguredException("Fee estimation returned a -1 error code") - elif estimateFeeResult.Result <= 0m then - return raise <| ServerMisconfiguredException(SPrintF1 "Fee estimation returned an invalid non-positive value %M" - estimateFeeResult.Result) - - let amountPerKB = estimateFeeResult.Result - let satPerKB = (NBitcoin.Money (amountPerKB, NBitcoin.MoneyUnit.BTC)).ToUnit NBitcoin.MoneyUnit.Satoshi - let satPerB = satPerKB / (decimal 1000) - Infrastructure.LogDebug <| SPrintF2 - "Electrum server gave us a fee rate of %M per KB = %M sat per B" amountPerKB satPerB - return amountPerKB - } - - let BroadcastTransaction (transactionInHex: string) (stratumServer: Async) = async { - let! stratumClient = stratumServer - let! blockchainTransactionBroadcastResult = stratumClient.BlockchainTransactionBroadcast transactionInHex - return blockchainTransactionBroadcastResult.Result - } - + async { + let! client = + Electrum.CreateClient + electrumServer.ServerInfo.NetworkPath + port + Config.DEFAULT_NETWORK_CONNECT_TIMEOUT + "geewallet" + client.Logger <- Infrastructure.LogDebug + return client + } + + let GetBalance (scriptHash: string) (electrumClient: Async) = + Electrum.GetBalances (List.singleton scriptHash) electrumClient diff --git a/src/GWallet.Backend/UtxoCoin/StratumClient.fs b/src/GWallet.Backend/UtxoCoin/StratumClient.fs deleted file mode 100644 index a9f0112b6..000000000 --- a/src/GWallet.Backend/UtxoCoin/StratumClient.fs +++ /dev/null @@ -1,331 +0,0 @@ -namespace GWallet.Backend.UtxoCoin - -open System -open System.ComponentModel - -open Newtonsoft.Json - -open GWallet.Backend -open GWallet.Backend.FSharpUtil.UwpHacks - -// can't make this type below private, or else Newtonsoft.Json will serialize it incorrectly -type Request = - { - Id: int; - Method: string; - Params: seq; - } - -type ServerVersionResult = - { - Id: int; - Result: array; - } - -type BlockchainScriptHashGetBalanceInnerResult = - { - Confirmed: Int64; - Unconfirmed: Int64; - } -type BlockchainScriptHashGetBalanceResult = - { - Id: int; - Result: BlockchainScriptHashGetBalanceInnerResult - } - -type BlockchainScriptHashListUnspentInnerResult = - { - TxHash: string; - TxPos: int; - Value: Int64; - Height: Int64; - } -type BlockchainScriptHashListUnspentResult = - { - Id: int; - Result: array - } - -type BlockchainTransactionGetResult = - { - Id: int; - Result: string; - } - -// DON'T DELETE, used in external projects -type BlockchainTransactionIdFromPosResult = - { - Id: int - Result: string - } - -type BlockchainEstimateFeeResult = - { - Id: int; - Result: decimal; - } - -type BlockchainTransactionBroadcastResult = - { - Id: int; - Result: string; - } - -type ErrorInnerResult = - { - Message: string; - Code: int; - } - -type ErrorResult = - { - Id: int; - Error: ErrorInnerResult; - } - -type ErrorResultWithStringError = - { - Id: int - Error: string - } - -type RpcErrorCode = - // see https://gitlab.com/nblockchain/geewallet/issues/110 - | ExcessiveResourceUsage = -101 - - // see https://gitlab.com/nblockchain/geewallet/issues/117 - | ServerBusy = -102 - - // see git commit msg of 0aba03a8291daa526fde888d0c02a789abe411f2 - | InternalError = -32603 - - // see https://gitlab.com/nblockchain/geewallet/issues/112 - | UnknownMethod = -32601 - -type public ElectrumServerReturningImproperJsonResponseException(message: string, innerEx: Exception) = - inherit ServerMisconfiguredException (message, innerEx) - -type public ElectrumServerReturningErrorInJsonResponseException(message: string, code: Option) = - inherit CommunicationUnsuccessfulException(message) - - member val ErrorCode: Option = - code with get - -type public ElectrumServerReturningErrorException(message: string, code: Option, - originalRequest: string, originalResponse: string) = - inherit ElectrumServerReturningErrorInJsonResponseException(message, code) - - member val OriginalRequest: string = - originalRequest with get - - member val OriginalResponse: string = - originalResponse with get - -type public ElectrumServerReturningInternalErrorException(message: string, code: Option, - originalRequest: string, originalResponse: string) = - inherit ElectrumServerReturningErrorException(message, code, originalRequest, originalResponse) - -type StratumClient (jsonRpcClient: JsonRpcTcpClient) = - - let Serialize(req: Request): string = - JsonConvert.SerializeObject(req, Formatting.None, - Marshalling.PascalCase2LowercasePlusUnderscoreConversionSettings) - - // TODO: add 'T as incoming request type, leave 'R as outgoing response type - member private self.Request<'R> (jsonRequest: string): Async<'R*string> = async { - let! rawResponse = jsonRpcClient.Request jsonRequest - - // FIXME: we should actually fix this bug in JsonRpcSharp (https://github.com/nblockchain/JsonRpcSharp/issues/9) - if String.IsNullOrEmpty rawResponse then - return raise <| ProtocolGlitchException(SPrintF2 "Server '%s' returned a null/empty JSON response to the request '%s'??" - jsonRpcClient.Host jsonRequest) - - try - return (StratumClient.Deserialize<'R> rawResponse, rawResponse) - with - | :? ElectrumServerReturningErrorInJsonResponseException as ex -> - if ex.ErrorCode = (RpcErrorCode.InternalError |> int |> Some) then - return raise(ElectrumServerReturningInternalErrorException(ex.Message, ex.ErrorCode, jsonRequest, rawResponse)) - if ex.ErrorCode = (RpcErrorCode.UnknownMethod |> int |> Some) then - return raise <| ServerMisconfiguredException(ex.Message, ex) - if ex.ErrorCode = (RpcErrorCode.ServerBusy |> int |> Some) then - return raise <| ServerFaultException(ex.Message, ex) - if ex.ErrorCode = (RpcErrorCode.ExcessiveResourceUsage |> int |> Some) then - return raise <| ServerFaultException(ex.Message, ex) - - return raise(ElectrumServerReturningErrorException(ex.Message, ex.ErrorCode, jsonRequest, rawResponse)) - } - - static member private DeserializeInternal<'T> (result: string): 'T = - let resultTrimmed = result.Trim() - - let maybeError: Choice = - let raiseDeserializationError (ex: Exception) = - raise <| Exception(SPrintF2 "Failed deserializing JSON response (to check for error) '%s' to type '%s'" - resultTrimmed typedefof<'T>.FullName, ex) - try - JsonConvert.DeserializeObject(resultTrimmed, - Marshalling.PascalCase2LowercasePlusUnderscoreConversionSettings) - |> Choice1Of2 - with - | :? JsonSerializationException -> - try - JsonConvert.DeserializeObject(resultTrimmed, - Marshalling.PascalCase2LowercasePlusUnderscoreConversionSettings) - |> Choice2Of2 - with - | ex -> - raiseDeserializationError ex - | ex -> - raiseDeserializationError ex - - match maybeError with - | Choice1Of2 errorResult when (not (Object.ReferenceEquals(errorResult, null))) && (not (Object.ReferenceEquals(errorResult.Error, null))) -> - raise <| ElectrumServerReturningErrorInJsonResponseException(errorResult.Error.Message, Some errorResult.Error.Code) - | Choice2Of2 errorResultWithStringError when (not (Object.ReferenceEquals(errorResultWithStringError, null))) && (not (String.IsNullOrWhiteSpace errorResultWithStringError.Error)) -> - raise <| ElectrumServerReturningErrorInJsonResponseException(errorResultWithStringError.Error, None) - | _ -> () - - let failedDeserMsg = SPrintF2 "Failed deserializing JSON response '%s' to type '%s'" - resultTrimmed typedefof<'T>.FullName - let deserializedValue = - try - JsonConvert.DeserializeObject<'T>(resultTrimmed, - Marshalling.PascalCase2LowercasePlusUnderscoreConversionSettings) - with - | :? Newtonsoft.Json.JsonSerializationException as serEx -> - let newEx = ElectrumServerReturningImproperJsonResponseException(failedDeserMsg, serEx) -#if !DEBUG - Infrastructure.ReportWarning newEx - |> ignore -#endif - raise newEx - | ex -> raise <| Exception(failedDeserMsg, ex) - - if Object.ReferenceEquals(deserializedValue, null) then - failwith <| SPrintF2 "Failed deserializing JSON response '%s' to type '%s' (result was null)" - resultTrimmed typedefof<'T>.FullName - - deserializedValue - - // TODO: should this validation actually be part of JsonRpcSharp? - static member public Deserialize<'T> (result: string): 'T = - match Marshalling.IsValidJson result with - | false -> - raise <| ServerMisconfiguredException(SPrintF1 "Server's reply was not valid json: %s" result) - | true -> - StratumClient.DeserializeInternal result - - member self.BlockchainScriptHashGetBalance address: Async = - let obj = { - Id = 0; - Method = "blockchain.scripthash.get_balance"; - Params = [address] - } - let json = Serialize obj - - async { - let! resObj,_ = self.Request json - return resObj - } - - static member private CreateVersion(versionStr: string): Version = - let correctedVersion = - if (versionStr.EndsWith("+")) then - versionStr.Substring(0, versionStr.Length - 1) - else - versionStr - try - Version(correctedVersion) - with - | exn -> raise(Exception("Electrum Server's version disliked by .NET Version class: " + versionStr, exn)) - - member self.ServerVersion (clientName: string) (protocolVersion: Version): Async = async { - let obj = { - Id = 0; - Method = "server.version"; - Params = [clientName; protocolVersion.ToString()] - } - // this below serializes to: - // (SPrintF2 "{ \"id\": 0, \"method\": \"server.version\", \"params\": [ \"%s\", \"%s\" ] }" - // CURRENT_ELECTRUM_FAKED_VERSION PROTOCOL_VERSION) - let json = Serialize obj - let! resObj, rawResponse = self.Request json - - if Object.ReferenceEquals (resObj, null) then - failwith <| SPrintF1 "resObj is null?? raw response was %s" rawResponse - - if Object.ReferenceEquals (resObj.Result, null) then - failwith <| SPrintF1 "resObj.Result is null?? raw response was %s" rawResponse - - // resObj.Result.[0] is e.g. "ElectrumX 1.4.3" - // e.g. "1.1" - let serverProtocolVersion = resObj.Result.[1] - - return StratumClient.CreateVersion(serverProtocolVersion) - } - - member self.BlockchainScriptHashListUnspent address: Async = - let obj = { - Id = 0; - Method = "blockchain.scripthash.listunspent"; - Params = [address] - } - let json = Serialize obj - async { - let! resObj,_ = self.Request json - return resObj - } - - member self.BlockchainTransactionGet txHash: Async = - let obj = { - Id = 0; - Method = "blockchain.transaction.get"; - Params = [txHash] - } - let json = Serialize obj - async { - let! resObj,_ = self.Request json - return resObj - } - - // DON'T DELETE, used in external projects - member self.BlockchainTransactionIdFromPos height txPos: Async = - let obj = { - Id = 0; - Method = "blockchain.transaction.id_from_pos"; - Params = [height :> obj; txPos :> obj] - } - let json = Serialize obj - async { - let! resObj,_ = self.Request json - return resObj - } - - // NOTE: despite Electrum-X official docs claiming that this method is deprecated... it's not! go read the official - // non-shitcoin forked version of the docs: https://electrumx-spesmilo.readthedocs.io/en/latest/protocol-methods.html#blockchain-estimatefee - member self.BlockchainEstimateFee (numBlocksTarget: int): Async = - let obj = { - Id = 0; - Method = "blockchain.estimatefee"; - Params = [numBlocksTarget] - } - let json = Serialize obj - - async { - let! resObj,_ = self.Request json - return resObj - } - - member self.BlockchainTransactionBroadcast txInHex: Async = - let obj = { - Id = 0; - Method = "blockchain.transaction.broadcast"; - Params = [txInHex] - } - let json = Serialize obj - - async { - let! resObj,_ = self.Request json - return resObj - } diff --git a/src/GWallet.Backend/UtxoCoin/UtxoCoinAccount.fs b/src/GWallet.Backend/UtxoCoin/UtxoCoinAccount.fs index 56cf8a76a..131dc582f 100644 --- a/src/GWallet.Backend/UtxoCoin/UtxoCoinAccount.fs +++ b/src/GWallet.Backend/UtxoCoin/UtxoCoinAccount.fs @@ -10,6 +10,7 @@ open System.Linq open NBitcoin open NBitcoin.Payment open Fsdk +open ElectrumSharp open GWallet.Backend open GWallet.Backend.FSharpUtil.UwpHacks @@ -112,7 +113,7 @@ module Account = | _ -> failwith <| SPrintF1 "Kind (%A) not supported for this API" kind - let private BalanceToShow (balances: BlockchainScriptHashGetBalanceInnerResult) = + let private BalanceToShow (balances: BlockchainScriptHashGetBalanceResult) = let unconfirmedPlusConfirmed = balances.Unconfirmed + balances.Confirmed let amountToShowInSatoshis,imminentIncomingPayment = if unconfirmedPlusConfirmed <= balances.Confirmed then @@ -124,7 +125,7 @@ module Account = let private BalanceMatchWithCacheOrInitialBalance address currency - (someRetrievedBalance: BlockchainScriptHashGetBalanceInnerResult) + (someRetrievedBalance: BlockchainScriptHashGetBalanceResult) : bool = let balanceFromServers,_ = BalanceToShow someRetrievedBalance if Caching.Instance.FirstRun then @@ -138,18 +139,18 @@ module Account = let private GetBalances (account: IUtxoAccount) (mode: ServerSelectionMode) (cancelSourceOption: Option) - : Async = + : Async = let scriptHashHex = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress let querySettings = QuerySettings.Balance(mode,(BalanceMatchWithCacheOrInitialBalance account.PublicAddress account.Currency)) - let balanceJob = ElectrumClient.GetBalance scriptHashHex + let balanceJob = Electrum.GetBalance scriptHashHex Server.Query account.Currency querySettings balanceJob cancelSourceOption let private GetBalancesFromServer (account: IUtxoAccount) (mode: ServerSelectionMode) (cancelSourceOption: Option) - : Async> = + : Async> = async { try let! balances = GetBalances account mode cancelSourceOption @@ -220,7 +221,7 @@ module Account = let private ConvertToInputOutpointInfo currency (utxo: UnspentTransactionOutputInfo) : Async = async { - let job = ElectrumClient.GetBlockchainTransaction utxo.TransactionId + let job = Electrum.GetBlockchainTransaction utxo.TransactionId let! transRaw = Server.Query currency (QuerySettings.Default ServerSelectionMode.Fast) job None let transaction = Transaction.Parse(transRaw, GetNetwork currency) @@ -295,7 +296,7 @@ module Account = newAcc,tail let job = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress - |> ElectrumClient.GetUnspentTransactionOutputs + |> Electrum.GetUnspentTransactionOutputs let! utxos = Server.Query account.Currency (QuerySettings.Default ServerSelectionMode.Fast) job None if not (utxos.Any()) then @@ -323,7 +324,7 @@ module Account = avg //querying for 1 will always return -1 surprisingly... - let estimateFeeJob = ElectrumClient.EstimateFee 2 + let estimateFeeJob = Electrum.EstimateFee 2 let! btcPerKiloByteForFastTrans = Server.Query account.Currency (QuerySettings.FeeEstimation averageFee) estimateFeeJob None @@ -439,7 +440,7 @@ module Account = let getInputAmount (input: TxIn) = async { - let job = ElectrumClient.GetBlockchainTransaction (input.PrevOut.Hash.ToString()) + let job = Electrum.GetBlockchainTransaction (input.PrevOut.Hash.ToString()) let! inputOriginTxString = Server.Query currency (QuerySettings.Default ServerSelectionMode.Fast) job None let inputOriginTx = Transaction.Parse (inputOriginTxString, network) return inputOriginTx.Outputs.[input.PrevOut.N].Value @@ -463,11 +464,11 @@ module Account = async { if not ignoreHigherMinerFeeThanAmount then do! ValidateMinerFee currency rawTx - let job = ElectrumClient.BroadcastTransaction rawTx + let job = Electrum.BroadcastTransaction rawTx return! Server.Query currency QuerySettings.Broadcast job None } - let internal BroadcastTransaction currency (transaction: SignedTransaction<_>) = + let internal BroadcastTransaction currency (transaction: SignedTransaction) = // FIXME: stop embedding TransactionInfo element in SignedTransaction // and show the info from the RawTx, using NBitcoin to extract it BroadcastRawTransaction currency transaction.RawTransaction @@ -477,14 +478,17 @@ module Account = (destination: string) (amount: TransferAmount) (password: string) - (ignoreHigherMinerFeeThanAmount: bool) - = - let baseAccount = account :> IAccount - if (baseAccount.PublicAddress.Equals(destination, StringComparison.InvariantCultureIgnoreCase)) then - raise DestinationEqualToOrigin - - let finalTransaction = SignTransaction account txMetadata destination amount password - BroadcastRawTransaction baseAccount.Currency finalTransaction ignoreHigherMinerFeeThanAmount + (ignoreHigherMinerFeeThanAmount: bool) = + async { + let baseAccount = account :> IAccount + if (baseAccount.PublicAddress.Equals(destination, StringComparison.InvariantCultureIgnoreCase)) then + raise DestinationEqualToOrigin + + let finalTransaction = SignTransaction account txMetadata destination amount password + let! txId = BroadcastRawTransaction baseAccount.Currency finalTransaction ignoreHigherMinerFeeThanAmount + + return txId, finalTransaction + } // TODO: maybe move this func to Backend.Account module, or simply inline it (simple enough) let public ExportUnsignedTransactionToJson trans = @@ -633,12 +637,58 @@ module Account = // TODO: propose to NBitcoin upstream to generate an NBitcoin exception instead | :? FormatException -> raise (AddressWithInvalidChecksum None) + + let GetTransactionFeeMetadata (signedTx: SignedTransaction): Async = + async { + let network = GetNetwork signedTx.Currency + let txToValidate = Transaction.Parse (signedTx.RawTransaction, network) - let GetSignedTransactionDetails<'T when 'T :> IBlockchainFeeInfo>(rawTransaction: string) - (currency: Currency) - : ITransactionDetails = - let network = GetNetwork currency - match Transaction.TryParse(rawTransaction, network) with + let totalOutputsAmount = txToValidate.TotalOut + + let getInputDetails (input: TxIn) = + async { + let job = Electrum.GetBlockchainTransaction (input.PrevOut.Hash.ToString()) + let! inputOriginTxString = Server.Query signedTx.Currency (QuerySettings.Default ServerSelectionMode.Fast) job None + let inputOriginTx = Transaction.Parse (inputOriginTxString, network) + return + input.PrevOut.N, + inputOriginTx.Outputs.[input.PrevOut.N], + inputOriginTx.GetHash().ToString() + } + + let! inputs = + txToValidate.Inputs + |> Seq.map getInputDetails + |> Async.Parallel + + let totalInputsAmount = + inputs + |> Seq.sumBy (fun (_outputIndex, txOut, _transactionHash) -> txOut.Value) + + let minerFee = totalInputsAmount - totalOutputsAmount + + return + { + TransactionMetadata.Fee = + MinerFee(minerFee.Satoshi, DateTime.Now, signedTx.FeeCurrency) + // We don't need inputs since the metadata object gets casted to IBlockchainFeeInfo + Inputs = + inputs + |> Seq.map(fun (outputIndex, txOut, transactionHash) -> + { + TransactionHash = transactionHash + OutputIndex = int outputIndex + ValueInSatoshis = txOut.Value.Satoshi + DestinationInHex = txOut.ScriptPubKey.ToHex() + } + ) + |> Seq.toList + } :> IBlockchainFeeInfo + } + + let GetSignedTransactionDetails (signedTx: SignedTransaction) : ITransactionDetails = + let network = GetNetwork signedTx.Currency + match Transaction.TryParse(signedTx.RawTransaction, network) with | false, _ -> failwith "malformed transaction" | true, transaction -> @@ -667,10 +717,10 @@ module Account = let account = let accountOpt = - Config.GetAccountFiles [currency] AccountKind.ReadOnly + Config.GetAccountFiles [signedTx.Currency] AccountKind.ReadOnly |> Seq.map (fun accountFile -> - GetAccountFromFile accountFile currency AccountKind.ReadOnly + GetAccountFromFile accountFile signedTx.Currency AccountKind.ReadOnly :?> ReadOnlyUtxoAccount ) |> Seq.filter matchOriginToAccount @@ -703,6 +753,14 @@ module Account = OriginAddress = originAddress.ToString() DestinationAddress = destinationAddress.ToString() Amount = value.ToDecimal MoneyUnit.BTC - Currency = currency + Currency = signedTx.Currency } :> ITransactionDetails + let GetSignedTransactionProposal (signedTx: SignedTransaction): UnsignedTransactionProposal = + let txDetail = GetSignedTransactionDetails signedTx + { + UnsignedTransactionProposal.Amount = + TransferAmount(txDetail.Amount, txDetail.Amount + 1m, txDetail.Currency) + OriginAddress = txDetail.OriginAddress + DestinationAddress = txDetail.DestinationAddress + } \ No newline at end of file diff --git a/src/GWallet.Backend/UtxoCoin/UtxoCoinServer.fs b/src/GWallet.Backend/UtxoCoin/UtxoCoinServer.fs index f5eb49dc3..531c96193 100644 --- a/src/GWallet.Backend/UtxoCoin/UtxoCoinServer.fs +++ b/src/GWallet.Backend/UtxoCoin/UtxoCoinServer.fs @@ -5,6 +5,8 @@ open System +open ElectrumSharp + open GWallet.Backend open GWallet.Backend.FSharpUtil.UwpHacks @@ -60,15 +62,15 @@ module Server = // FIXME: seems there's some code duplication between this function and EtherServer.fs's GetServerFuncs function // and room for simplification to not pass a new ad-hoc delegate? - let internal GetServerFuncs<'R> (electrumClientFunc: Async->Async<'R>) + let internal GetServerFuncs<'R> (electrumClientFunc: Async->Async<'R>) (electrumServers: seq) : seq> = let ElectrumServerToRetrievalFunc (server: ServerDetails) - (electrumClientFunc: Async->Async<'R>) + (electrumClientFunc: Async->Async<'R>) : Async<'R> = async { try - let stratumClient = ElectrumClient.StratumServer server + let stratumClient = Electrum.CreateClientFor server return! electrumClientFunc stratumClient // NOTE: try to make this 'with' block be in sync with the one in EtherServer:GetWeb3Funcs() @@ -80,7 +82,7 @@ module Server = return raise <| Exception(SPrintF1 "Some problem when connecting to %s" server.ServerInfo.NetworkPath, ex) } - let ElectrumServerToGenericServer (electrumClientFunc: Async->Async<'R>) + let ElectrumServerToGenericServer (electrumClientFunc: Async->Async<'R>) (electrumServer: ServerDetails) : Server = { @@ -94,7 +96,7 @@ module Server = serverFuncs let private GetRandomizedFuncs<'R> (currency: Currency) - (electrumClientFunc: Async->Async<'R>) + (electrumClientFunc: Async->Async<'R>) : List> = let electrumServers = ElectrumServerSeedList.Randomize currency @@ -103,7 +105,7 @@ module Server = let Query<'R when 'R: equality> currency (settings: QuerySettings<'R>) - (job: Async->Async<'R>) + (job: Async->Async<'R>) (cancelSourceOption: Option) : Async<'R> = let query = @@ -122,6 +124,15 @@ module Server = ServerSelectionMode.Fast (Some (AverageBetweenResponses (minResponsesRequired, averageFee))) | Broadcast -> FaultTolerantParallelClientSettingsForBroadcast() - query - querySettings - (GetRandomizedFuncs currency job) + async { + try + return! query + querySettings + (GetRandomizedFuncs currency job) + with + | ex -> + match Fsdk.FSharpUtil.FindException ex with + | Some commFailedExn -> + return raise <| CommunicationUnsuccessfulException(commFailedExn.Message, commFailedExn) + | None -> return raise ex + } diff --git a/src/GWallet.Backend/packages.config b/src/GWallet.Backend/packages.config index aa604ee0d..6fbfffe7f 100644 --- a/src/GWallet.Backend/packages.config +++ b/src/GWallet.Backend/packages.config @@ -1,19 +1,21 @@  + - + + + - - + - + @@ -33,11 +35,11 @@ - + - + @@ -65,7 +67,7 @@ - + diff --git a/src/GWallet.Frontend.Console/App.config b/src/GWallet.Frontend.Console/App.config index 1778ee567..ea1b18b2b 100644 --- a/src/GWallet.Frontend.Console/App.config +++ b/src/GWallet.Frontend.Console/App.config @@ -4,7 +4,7 @@ - + @@ -14,6 +14,18 @@ + + + + + + + + + + + + diff --git a/src/GWallet.Frontend.Console/GWallet.Frontend.Console-legacy.fsproj b/src/GWallet.Frontend.Console/GWallet.Frontend.Console-legacy.fsproj index 2cf63c863..989b045ae 100644 --- a/src/GWallet.Frontend.Console/GWallet.Frontend.Console-legacy.fsproj +++ b/src/GWallet.Frontend.Console/GWallet.Frontend.Console-legacy.fsproj @@ -11,7 +11,7 @@ GWallet.Frontend.Console v4.7.1 true - 4.7.0.0 + 6.0.0.0 GWallet.Frontend.Console @@ -91,7 +91,7 @@ ..\..\packages\Fsdk.0.6.0--date20230530-1155.git-3bb8d08\lib\netstandard2.0\Fsdk.dll - ..\..\packages\FSharp.Core.4.7.0\lib\net45\FSharp.Core.dll + ..\..\packages\FSharp.Core.6.0.1\lib\netstandard2.0\FSharp.Core.dll ..\..\packages\SharpRaven.2.4.0\lib\net471\SharpRaven.dll diff --git a/src/GWallet.Frontend.Console/Program.fs b/src/GWallet.Frontend.Console/Program.fs index e72719238..f2c6b65c7 100644 --- a/src/GWallet.Frontend.Console/Program.fs +++ b/src/GWallet.Frontend.Console/Program.fs @@ -80,9 +80,14 @@ let BroadcastPayment() = | Some signedTransaction -> let transactionDetails = Account.GetSignedTransactionDetails signedTransaction + let transactionMetadata = + signedTransaction + |> Account.GetTransactionMetadata + |> Async.RunSynchronously + Presentation.ShowTransactionData transactionDetails - signedTransaction.TransactionInfo.Metadata + transactionMetadata if UserInteraction.AskYesNo "Do you accept?" then try diff --git a/src/GWallet.Frontend.Console/packages.config b/src/GWallet.Frontend.Console/packages.config index 5c6be0787..024a5ce66 100644 --- a/src/GWallet.Frontend.Console/packages.config +++ b/src/GWallet.Frontend.Console/packages.config @@ -1,6 +1,6 @@  - + diff --git a/src/GWallet.Frontend.XF.Android/GWallet.Frontend.XF.Android.fsproj b/src/GWallet.Frontend.XF.Android/GWallet.Frontend.XF.Android.fsproj index 1b60db231..01f4ad920 100644 --- a/src/GWallet.Frontend.XF.Android/GWallet.Frontend.XF.Android.fsproj +++ b/src/GWallet.Frontend.XF.Android/GWallet.Frontend.XF.Android.fsproj @@ -49,6 +49,66 @@ + + ..\..\packages\ADRaffy.ENSNormalize.0.1.5\lib\netstandard2.0\ADRaffy.ENSNormalize.dll + + + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.ABI.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Accounts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.BlockchainProcessing.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Contracts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Hex.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.Client.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.RpcClient.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.KeyStore.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Merkle.Patricia.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Model.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RLP.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RPC.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.EIP712.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Util.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Web3.dll + @@ -63,6 +123,15 @@ ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\..\packages\System.Reflection.Emit.4.7.0\lib\netstandard2.0\System.Reflection.Emit.dll + + + ..\..\packages\System.Reflection.Emit.Lightweight.4.7.0\lib\netstandard2.0\System.Reflection.Emit.Lightweight.dll + + + ..\..\packages\ElectrumSharp.0.0.0.2--date20240416-0821.git-3367808\lib\netstandard2.0\ElectrumSharp.dll + ..\..\packages\DotNetEssentials.1.6.1--date20220823-0234.git-14ad2d3\lib\monoandroid10.0\Xamarin.Essentials.dll @@ -267,7 +336,7 @@ ..\..\packages\FastAndroidCamera.2.0.0\lib\MonoAndroid403\FastAndroidCamera.dll - ..\..\packages\FSharp.Core.4.7.0\lib\netstandard2.0\FSharp.Core.dll + ..\..\packages\FSharp.Core.6.0.1\lib\netstandard2.0\FSharp.Core.dll ..\..\packages\FSharp.Data.3.0.0\lib\netstandard2.0\FSharp.Data.dll @@ -275,62 +344,50 @@ ..\..\packages\HtmlAgilityPack.1.11.24\lib\netstandard2.0\HtmlAgilityPack.dll - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.Client.dll - - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.IpcClient.dll - - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.HttpClient.dll - - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.TcpClient.dll - - - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.WebSocketClient.dll + + ..\..\packages\System.Text.Json.7.0.3\lib\netstandard2.0\System.Text.Json.dll - - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll + + ..\..\packages\System.Text.Encodings.Web.7.0.0\lib\netstandard2.0\System.Text.Encodings.Web.dll - - ..\..\packages\NBitcoin.6.0.17\lib\netstandard2.1\NBitcoin.dll + + ..\..\packages\StreamJsonRpc.2.17.11\lib\netstandard2.0\StreamJsonRpc.dll - - ..\..\packages\NBitcoin.Altcoins.3.0.8\lib\netstandard2.1\NBitcoin.Altcoins.dll + + ..\..\packages\MessagePack.2.5.108\lib\netstandard2.0\MessagePack.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.ABI.dll + + ..\..\packages\MessagePack.Annotations.2.5.108\lib\netstandard2.0\MessagePack.Annotations.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Accounts.dll + + ..\..\packages\Nerdbank.Streams.2.10.69\lib\netstandard2.0\Nerdbank.Streams.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Contracts.dll + + ..\..\packages\System.Diagnostics.DiagnosticSource.7.0.2\lib\netstandard2.0\System.Diagnostics.DiagnosticSource.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Hex.dll + + ..\..\packages\System.Threading.Tasks.Dataflow.7.0.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.KeyStore.dll + + ..\..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\netstandard2.0\Microsoft.Bcl.AsyncInterfaces.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RLP.dll + + ..\..\packages\Microsoft.NET.StringTools.17.4.0\lib\netstandard2.0\Microsoft.NET.StringTools.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RPC.dll + + ..\..\packages\Microsoft.VisualStudio.Threading.17.7.35\lib\netstandard2.0\Microsoft.VisualStudio.Threading.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Signer.dll + + ..\..\packages\Microsoft.VisualStudio.Threading.Analyzers.17.7.35\lib\netstandard2.0\Microsoft.VisualStudio.Threading.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + + ..\..\packages\Microsoft.VisualStudio.Validation.17.6.11\lib\netstandard2.0\Microsoft.VisualStudio.Validation.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Util.dll + + ..\..\packages\NBitcoin.6.0.17\lib\netstandard2.1\NBitcoin.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Web3.dll + + ..\..\packages\NBitcoin.Altcoins.3.0.8\lib\netstandard2.1\NBitcoin.Altcoins.dll ..\..\packages\Newtonsoft.Json.13.0.2\lib\netstandard2.0\Newtonsoft.Json.dll @@ -346,11 +403,14 @@ ..\..\packages\System.Configuration.ConfigurationManager.4.4.0\lib\netstandard2.0\System.Configuration.ConfigurationManager.dll - ..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll + ..\..\packages\System.IO.Pipelines.7.0.0\lib\netstandard2.0\System.IO.Pipelines.dll + + + ..\..\packages\System.Collections.Immutable.7.0.0\lib\netstandard2.0\System.Collections.Immutable.dll True - ..\..\packages\System.Memory.4.5.4\lib\netstandard2.0\System.Memory.dll + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll ..\..\packages\Xamarin.Android.Arch.Core.Common.1.1.1.3\lib\monoandroid90\Xamarin.Android.Arch.Core.Common.dll @@ -556,6 +616,7 @@ + @@ -665,4 +726,5 @@ + diff --git a/src/GWallet.Frontend.XF.Android/packages.config b/src/GWallet.Frontend.XF.Android/packages.config index 87848d06f..6437b4795 100644 --- a/src/GWallet.Frontend.XF.Android/packages.config +++ b/src/GWallet.Frontend.XF.Android/packages.config @@ -1,20 +1,30 @@  + - + - + + + + - + + + + + + + - + @@ -24,10 +34,12 @@ + + @@ -38,10 +50,10 @@ - + - + @@ -49,6 +61,8 @@ + + @@ -68,10 +82,13 @@ + + - + + diff --git a/src/GWallet.Frontend.XF.Gtk/GWallet.Frontend.XF.Gtk.fsproj b/src/GWallet.Frontend.XF.Gtk/GWallet.Frontend.XF.Gtk.fsproj index ce3686c54..d878bccb3 100644 --- a/src/GWallet.Frontend.XF.Gtk/GWallet.Frontend.XF.Gtk.fsproj +++ b/src/GWallet.Frontend.XF.Gtk/GWallet.Frontend.XF.Gtk.fsproj @@ -36,7 +36,67 @@ $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + ..\..\packages\ADRaffy.ENSNormalize.0.1.5\lib\net461\ADRaffy.ENSNormalize.dll + + + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.ABI.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Accounts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.BlockchainProcessing.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Contracts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Hex.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.Client.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.RpcClient.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.KeyStore.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Merkle.Patricia.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Model.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RLP.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RPC.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.EIP712.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Util.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Web3.dll + @@ -110,13 +170,13 @@ ..\..\packages\FSharp.Data.3.0.0\lib\net45\FSharp.Data.dll - ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll - ..\..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll - ..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll + ..\..\packages\System.IO.Pipelines.7.0.0\lib\netstandard2.0\System.IO.Pipelines.dll ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll @@ -130,9 +190,6 @@ ..\..\packages\ZXing.Net.Xamarin.Forms.3.0.0--date20220902-0549.git-462686e\lib\netstandard2.0\ZXing.Net.Mobile.Forms.dll - - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll - ..\..\packages\System.IO.Pipes.4.3.0\lib\net46\System.IO.Pipes.dll @@ -160,39 +217,6 @@ ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.WebSocketClient.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.ABI.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Accounts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Contracts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Hex.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.KeyStore.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RLP.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RPC.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Signer.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Util.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Web3.dll - ..\..\packages\HtmlAgilityPack.1.11.24\lib\Net45\HtmlAgilityPack.dll @@ -260,4 +284,11 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. + + + diff --git a/src/GWallet.Frontend.XF.Gtk/packages.config b/src/GWallet.Frontend.XF.Gtk/packages.config index a96baa6b8..804e1a217 100644 --- a/src/GWallet.Frontend.XF.Gtk/packages.config +++ b/src/GWallet.Frontend.XF.Gtk/packages.config @@ -1,5 +1,6 @@  + @@ -9,10 +10,10 @@ - + - + @@ -22,10 +23,10 @@ - + - + @@ -42,7 +43,7 @@ - + diff --git a/src/GWallet.Frontend.XF.Mac/GWallet.Frontend.XF.Mac.fsproj b/src/GWallet.Frontend.XF.Mac/GWallet.Frontend.XF.Mac.fsproj index 31032e2a0..1408ff357 100644 --- a/src/GWallet.Frontend.XF.Mac/GWallet.Frontend.XF.Mac.fsproj +++ b/src/GWallet.Frontend.XF.Mac/GWallet.Frontend.XF.Mac.fsproj @@ -49,6 +49,66 @@ + + ..\..\packages\ADRaffy.ENSNormalize.0.1.5\lib\netstandard2.0\ADRaffy.ENSNormalize.dll + + + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.ABI.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Accounts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.BlockchainProcessing.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Contracts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Hex.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.Client.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.RpcClient.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.KeyStore.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Merkle.Patricia.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Model.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RLP.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RPC.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.EIP712.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Util.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Web3.dll + @@ -78,7 +138,7 @@ ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\packages\System.Memory.4.5.4\lib\netstandard2.0\System.Memory.dll + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll ..\..\packages\System.Buffers.4.5.1\lib\netstandard2.0\System.Buffers.dll @@ -117,9 +177,6 @@ ..\..\packages\FSharp.Core.4.7.0\lib\netstandard2.0\FSharp.Core.dll - - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.Client.dll @@ -135,39 +192,6 @@ ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.WebSocketClient.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.ABI.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Accounts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Contracts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Hex.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.KeyStore.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RLP.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RPC.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Signer.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Util.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Web3.dll - ..\..\packages\HtmlAgilityPack.1.11.24\lib\netstandard2.0\HtmlAgilityPack.dll @@ -222,4 +246,11 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. + + + diff --git a/src/GWallet.Frontend.XF.Mac/packages.config b/src/GWallet.Frontend.XF.Mac/packages.config index 51a86c052..26de0709f 100644 --- a/src/GWallet.Frontend.XF.Mac/packages.config +++ b/src/GWallet.Frontend.XF.Mac/packages.config @@ -1,5 +1,6 @@  + @@ -8,12 +9,12 @@ - + - + @@ -40,7 +41,7 @@ - + @@ -70,7 +71,7 @@ - + diff --git a/src/GWallet.Frontend.XF.iOS/GWallet.Frontend.XF.iOS.fsproj b/src/GWallet.Frontend.XF.iOS/GWallet.Frontend.XF.iOS.fsproj index 3d8017712..be0151f4f 100644 --- a/src/GWallet.Frontend.XF.iOS/GWallet.Frontend.XF.iOS.fsproj +++ b/src/GWallet.Frontend.XF.iOS/GWallet.Frontend.XF.iOS.fsproj @@ -153,6 +153,66 @@ + + ..\..\packages\ADRaffy.ENSNormalize.0.1.5\lib\netstandard2.0\ADRaffy.ENSNormalize.dll + + + ..\..\packages\Microsoft.Extensions.Logging.Abstractions.6.0.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.ABI.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Accounts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.BlockchainProcessing.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Contracts.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Hex.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.Client.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.JsonRpc.RpcClient.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.KeyStore.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Merkle.Patricia.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Model.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RLP.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.RPC.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Signer.EIP712.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Util.dll + + + ..\..\packages\Nethereum.3.99.0--date20231003-1147.git-b9a16cf\lib\netstandard2.0\Nethereum.Web3.dll + @@ -193,7 +253,7 @@ ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\packages\System.Memory.4.5.4\lib\netstandard2.0\System.Memory.dll + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll ..\..\packages\System.Buffers.4.5.1\lib\netstandard2.0\System.Buffers.dll @@ -215,7 +275,7 @@ ..\..\packages\FSharp.Data.3.0.0\lib\netstandard2.0\FSharp.Data.dll - ..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll + ..\..\packages\System.IO.Pipelines.7.0.0\lib\netstandard2.0\System.IO.Pipelines.dll ..\..\packages\ZXing.Net.Xamarin.3.0.0--date20220902-0549.git-462686e\lib\xamarinios10\ZXingNetMobile.dll @@ -226,9 +286,6 @@ ..\..\packages\FSharp.Core.4.7.0\lib\netstandard2.0\FSharp.Core.dll - - ..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.0.2\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll - ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.Client.dll @@ -244,39 +301,6 @@ ..\..\packages\JsonRpcSharp.0.98.0--date20230731-1252.git-6788e32\lib\netstandard2.0\JsonRpcSharp.WebSocketClient.dll - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.ABI.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Accounts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Contracts.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Hex.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.KeyStore.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RLP.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.RPC.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Signer.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.StandardTokenEIP20.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Util.dll - - - ..\..\packages\Nethereum.0.95.0--date20210125-0551.git-05a29e9\lib\netstandard2.0\Nethereum.Web3.dll - ..\..\packages\HtmlAgilityPack.1.11.24\lib\netstandard2.0\HtmlAgilityPack.dll @@ -295,4 +319,11 @@ + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. + + + diff --git a/src/GWallet.Frontend.XF.iOS/packages.config b/src/GWallet.Frontend.XF.iOS/packages.config index a8e21708f..e7b45088a 100644 --- a/src/GWallet.Frontend.XF.iOS/packages.config +++ b/src/GWallet.Frontend.XF.iOS/packages.config @@ -1,5 +1,6 @@  + @@ -8,12 +9,12 @@ - + - + @@ -37,10 +38,10 @@ - + - + @@ -70,7 +71,7 @@ - + diff --git a/src/GWallet.Frontend.XF/GWallet.Frontend.XF.fsproj b/src/GWallet.Frontend.XF/GWallet.Frontend.XF.fsproj index 0cfc7078e..09d2e8aa7 100644 --- a/src/GWallet.Frontend.XF/GWallet.Frontend.XF.fsproj +++ b/src/GWallet.Frontend.XF/GWallet.Frontend.XF.fsproj @@ -133,7 +133,7 @@ Code - + diff --git a/src/GWallet.Frontend.XF/SendPage.xaml.fs b/src/GWallet.Frontend.XF/SendPage.xaml.fs index fbdc062cf..6ac9a6da4 100644 --- a/src/GWallet.Frontend.XF/SendPage.xaml.fs +++ b/src/GWallet.Frontend.XF/SendPage.xaml.fs @@ -25,7 +25,7 @@ type TransactionProposal<'T when 'T :> IBlockchainFeeInfo> = // cold wallet about to scan proposal from hot wallet: | ColdStorageMode of Option> // hot wallet about to broadcast transaction of ReadOnly account: - | ColdStorageRemoteControl of Option> + | ColdStorageRemoteControl of Option type SendPage(account: IAccount, receivePage: Page, newReceivePageFunc: unit->Page) as self = inherit ContentPage() @@ -439,15 +439,16 @@ type SendPage(account: IAccount, receivePage: Page, newReceivePageFunc: unit->Pa passwordEntry.Focus() |> ignore ) | Some (Signed signedTransaction) -> - if account.Currency <> signedTransaction.TransactionInfo.Proposal.Amount.Currency then + let proposal = Account.GetTransactionProposal signedTransaction + if account.Currency <> proposal.Amount.Currency then MainThread.BeginInvokeOnMainThread(fun _ -> transactionEntry.TextColor <- Color.Red let err = SPrintF2 "Transaction's currency (%A) doesn't match with this currency's account (%A)" - signedTransaction.TransactionInfo.Proposal.Amount.Currency account.Currency + proposal.Amount.Currency account.Currency self.DisplayAlert("Alert", err, "OK") |> FrontendHelpers.DoubleCheckCompletionNonGeneric ) - elif account.PublicAddress <> signedTransaction.TransactionInfo.Proposal.OriginAddress then + elif account.PublicAddress <> proposal.OriginAddress then MainThread.BeginInvokeOnMainThread(fun _ -> transactionEntry.TextColor <- Color.Red let err = "Transaction's sender address doesn't match with this currency's account" @@ -612,7 +613,12 @@ type SendPage(account: IAccount, receivePage: Page, newReceivePageFunc: unit->Pa match maybeRawTransaction with | None -> () | Some rawTransaction -> - let signedTransaction = { TransactionInfo = unsignedTransaction; RawTransaction = rawTransaction } + let signedTransaction = + { + Currency = unsignedTransaction.Proposal.Amount.Currency + FeeCurrency = unsignedTransaction.Metadata.Currency + RawTransaction = rawTransaction + } let compressedTransaction = Account.SerializeSignedTransaction signedTransaction true let pairSignedTransactionPage () = PairingFromPage(self, "Copy signed transaction to the clipboard", compressedTransaction, None)