@@ -72,12 +72,23 @@ module Account =
7272 // TODO: measure how long does it take to get the script hash and if it's too long, cache it at app startup?
7373 BitcoinAddress.Create( publicAddress, GetNetwork currency) |> GetElectrumScriptHashFromAddress
7474
75- let internal GetPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
75+ let internal GetSegwitP2shPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
76+ publicKey
77+ .GetScriptPubKey( ScriptPubKeyType.SegwitP2SH)
78+ .GetDestinationAddress( GetNetwork currency)
79+ .ToString()
80+
81+ let internal GetNativeSegwitPublicAddressFromPublicKey currency ( publicKey : PubKey ) =
7682 publicKey
7783 .GetScriptPubKey( ScriptPubKeyType.Segwit)
78- .Hash
79- .GetAddress( GetNetwork currency)
84+ .GetDestinationAddress( GetNetwork currency)
8085 .ToString()
86+
87+ let internal GetPublicAddressFromPublicKey =
88+ if Config.UseNativeSegwit then
89+ GetNativeSegwitPublicAddressFromPublicKey
90+ else
91+ GetSegwitP2shPublicAddressFromPublicKey
8192
8293 let internal GetPublicAddressFromNormalAccountFile ( currency : Currency ) ( accountFile : FileRepresentation ): string =
8394 let pubKey = PubKey( accountFile.Name)
@@ -139,11 +150,17 @@ module Account =
139150 ( mode : ServerSelectionMode )
140151 ( cancelSourceOption : Option < CustomCancelSource >)
141152 : Async < BlockchainScriptHashGetBalanceInnerResult > =
142- let scriptHashHex = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress
153+ let scriptHashesHex =
154+ [
155+ GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey
156+ |> GetElectrumScriptHashFromPublicAddress account.Currency
157+ GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey
158+ |> GetElectrumScriptHashFromPublicAddress account.Currency
159+ ]
143160
144161 let querySettings =
145162 QuerySettings.Balance( mode,( BalanceMatchWithCacheOrInitialBalance account.PublicAddress account.Currency))
146- let balanceJob = ElectrumClient.GetBalance scriptHashHex
163+ let balanceJob = ElectrumClient.GetBalances scriptHashesHex
147164 Server.Query account.Currency querySettings balanceJob cancelSourceOption
148165
149166 let private GetBalancesFromServer ( account : IUtxoAccount )
@@ -176,9 +193,21 @@ module Account =
176193 let txHash = uint256 inputOutpointInfo.TransactionHash
177194 let scriptPubKeyInBytes = NBitcoin.DataEncoders.Encoders.Hex.DecodeData inputOutpointInfo.DestinationInHex
178195 let scriptPubKey = Script( scriptPubKeyInBytes)
196+ // We convert the scriptPubKey to address temporarily to compare it with
197+ // our own addresses, we could compare scriptPubKeys directly but we would
198+ // need functions that return scriptPubKey of our addresses instead of a
199+ // string.
200+ let sourceAddress = scriptPubKey.GetDestinationAddress( GetNetwork account.Currency) .ToString()
179201 let coin =
180202 Coin( txHash, uint32 inputOutpointInfo.OutputIndex, Money( inputOutpointInfo.ValueInSatoshis), scriptPubKey)
181- coin.ToScriptCoin account.PublicKey.WitHash.ScriptPubKey :> ICoin
203+ if sourceAddress = GetSegwitP2shPublicAddressFromPublicKey account.Currency account.PublicKey then
204+ coin.ToScriptCoin( account.PublicKey.WitHash.ScriptPubKey) :> ICoin
205+ elif sourceAddress = GetNativeSegwitPublicAddressFromPublicKey account.Currency account.PublicKey then
206+ coin :> ICoin
207+ else
208+ //We filter utxos based on scriptPubKey when retrieving from electrum
209+ //so this is unreachable.
210+ failwith " Unreachable: unrecognized scriptPubKey"
182211
183212 let private CreateTransactionAndCoinsToBeSigned ( account : IUtxoAccount )
184213 ( transactionInputs : List < TransactionInputOutpointInfo >)
@@ -294,9 +323,28 @@ module Account =
294323 else
295324 newAcc, tail
296325
297- let job = GetElectrumScriptHashFromPublicAddress account.Currency account.PublicAddress
298- |> ElectrumClient.GetUnspentTransactionOutputs
299- let! utxos = Server.Query account.Currency ( QuerySettings.Default ServerSelectionMode.Fast) job None
326+ let currency = account.Currency
327+
328+ let getUtxos ( publicAddress : string ) =
329+ async {
330+ let job = GetElectrumScriptHashFromPublicAddress currency publicAddress
331+ |> ElectrumClient.GetUnspentTransactionOutputs
332+
333+ return ! Server.Query currency ( QuerySettings.Default ServerSelectionMode.Fast) job None
334+ }
335+
336+ let! utxos =
337+ async {
338+ let! nativeSegwitUtxos =
339+ GetNativeSegwitPublicAddressFromPublicKey currency account.PublicKey
340+ |> getUtxos
341+
342+ let! legacySegwitUtxos =
343+ GetSegwitP2shPublicAddressFromPublicKey currency account.PublicKey
344+ |> getUtxos
345+
346+ return Seq.concat [ nativeSegwitUtxos; legacySegwitUtxos ]
347+ }
300348
301349 if not ( utxos.Any()) then
302350 failwith " No UTXOs found!"
0 commit comments