public Task <UTXOChanges> GetUTXOsAsync(DerivationStrategyBase extKey, Bookmark[] confirmedBookmarks, Bookmark[] unconfirmedBookmarks, bool longPolling = true, CancellationToken cancellation = default)
 {
     if (extKey == null)
     {
         throw new ArgumentNullException(nameof(extKey));
     }
     return(GetUTXOsAsync(TrackedSource.Create(extKey), confirmedBookmarks, unconfirmedBookmarks, longPolling, cancellation));
 }
 public BitcoinConnector(string oracleAddress, string endpoint, Channel <Deposit> depositStream, Channel <WithdrawInfo> withdrawStream)
 {
     this.depositStream  = depositStream;
     this.withdrawStream = withdrawStream;
     this.oracleAddress  = TrackedSource.Create(new BitcoinPubKeyAddress(oracleAddress));
     client = new ExplorerClient(new NBXplorerNetworkProvider(NetworkType.Testnet).GetBTC(), new Uri(endpoint));
     client.SetNoAuth();
 }
Beispiel #3
0
 public Task <UTXOChanges> GetUTXOsAsync(DerivationStrategyBase extKey, CancellationToken cancellation = default)
 {
     if (extKey == null)
     {
         throw new ArgumentNullException(nameof(extKey));
     }
     return(GetUTXOsAsync(TrackedSource.Create(extKey), cancellation));
 }
Beispiel #4
0
        private void UpdateTxConfirmations(WalletAddr addr)
        {
            var baddr         = BitcoinAddress.Create(addr.Address, GetNetwork());
            var trackedSource = TrackedSource.Create(baddr);
            var txs           = GetClient().GetTransactions(trackedSource);

            UpdateTxConfirmations(txs);
        }
    public async Task TrackClaim(PaymentMethodId paymentMethodId, IClaimDestination claimDestination)
    {
        var network        = _btcPayNetworkProvider.GetNetwork <BTCPayNetwork>(paymentMethodId.CryptoCode);
        var explorerClient = _explorerClientProvider.GetExplorerClient(network);

        if (claimDestination is IBitcoinLikeClaimDestination bitcoinLikeClaimDestination)
        {
            await explorerClient.TrackAsync(TrackedSource.Create(bitcoinLikeClaimDestination.Address));
        }
    }
        public Task <TrackedSource> ConstructTrackedSource()
        {
            var data = GetData();

            var explorerClient = _nbXplorerClientProvider.GetClient(data.CryptoCode);
            var factory        = explorerClient.Network.DerivationStrategyFactory;

            if (string.IsNullOrEmpty(data
                                     .DerivationStrategy))
            {
                return(Task.FromResult <TrackedSource>(TrackedSource.Create(BitcoinAddress.Create(
                                                                                data.Address,
                                                                                explorerClient.Network.NBitcoinNetwork))));
            }
            else
            {
                return(Task.FromResult <TrackedSource>(TrackedSource.Create(_derivationSchemeParser.Parse(factory,
                                                                                                          data.DerivationStrategy))));
            }
        }
 public Task <GetTransactionsResponse> GetTransactionsAsync(DerivationStrategyBase strategy, Bookmark[] confirmedBookmarks, Bookmark[] unconfirmedBookmarks, Bookmark[] replacedBookmarks, bool longPolling, CancellationToken cancellation = default)
 {
     return(GetTransactionsAsync(TrackedSource.Create(strategy), confirmedBookmarks, unconfirmedBookmarks, replacedBookmarks, longPolling, cancellation));
 }
 public Task TrackAsync(DerivationStrategyBase strategy, CancellationToken cancellation = default)
 {
     return(TrackAsync(TrackedSource.Create(strategy), cancellation));
 }
Beispiel #9
0
 public Task <GetTransactionsResponse> GetTransactionsAsync(DerivationStrategyBase strategy, CancellationToken cancellation = default)
 {
     return(GetTransactionsAsync(TrackedSource.Create(strategy), cancellation));
 }
Beispiel #10
0
 public static void WaitForTransaction(this LongPollingNotificationSession session, BitcoinAddress address, uint256 txId)
 {
     session.WaitForTransaction(TrackedSource.Create(address), txId);
 }
Beispiel #11
0
 public static void WaitForTransaction(this LongPollingNotificationSession session, DerivationStrategyBase derivationStrategy, uint256 txId)
 {
     session.WaitForTransaction(TrackedSource.Create(derivationStrategy), txId);
 }
Beispiel #12
0
        BuildModel(EditNBXplorerWalletExternalServiceDataViewModel viewModel, ExternalServiceData mainModel)
        {
            var failureViewModel = new EditNBXplorerWalletExternalServiceDataViewModel(viewModel);

            failureViewModel.CryptoCodes = new SelectList(_nbXplorerOptions.Cryptos?.ToList() ?? new List <string>(),
                                                          viewModel.CryptoCode);

            if (viewModel.Action.Equals("add-private-key", StringComparison.InvariantCultureIgnoreCase))
            {
                failureViewModel.PrivateKeys.Add(new PrivateKeyDetails());
                return(null, failureViewModel);
            }

            if (viewModel.Action.StartsWith("remove-private-key", StringComparison.InvariantCultureIgnoreCase))
            {
                var index = int.Parse(viewModel.Action.Substring(viewModel.Action.IndexOf(":") + 1));
                failureViewModel.PrivateKeys.RemoveAt(index);
                return(null, failureViewModel);
            }

            if ((!string.IsNullOrEmpty(viewModel.DerivationStrategy) && !string.IsNullOrEmpty(viewModel.Address)) ||
                string.IsNullOrEmpty(viewModel.DerivationStrategy) && string.IsNullOrEmpty(viewModel.Address))
            {
                ModelState.AddModelError(string.Empty,
                                         "Please choose to track either an address OR a derivation scheme");
            }

            var client = _nbXplorerClientProvider.GetClient(viewModel.CryptoCode);

            BitcoinAddress         address            = null;
            DerivationStrategyBase derivationStrategy = null;

            if (!string.IsNullOrEmpty(viewModel.Address) && !string.IsNullOrEmpty(viewModel.CryptoCode))
            {
                try
                {
                    var factory = client.Network.DerivationStrategyFactory;
                    address = BitcoinAddress.Create(viewModel.Address, factory.Network);
                }
                catch (Exception)
                {
                    ModelState.AddModelError(nameof(viewModel.Address), "Invalid Address");
                }
            }

            if (!string.IsNullOrEmpty(viewModel.DerivationStrategy) && !string.IsNullOrEmpty(viewModel.CryptoCode))
            {
                try
                {
                    var factory = client.Network.DerivationStrategyFactory;

                    derivationStrategy = _derivationSchemeParser.Parse(factory, viewModel.DerivationStrategy);
                }
                catch
                {
                    ModelState.AddModelError(nameof(viewModel.DerivationStrategy), "Invalid Derivation Scheme");
                }
            }

            //current External Service data
            var externalServiceData = mainModel;

            externalServiceData.Set(viewModel);
            if (!ModelState.IsValid)
            {
                return(null, failureViewModel);
            }

            if (derivationStrategy != null)
            {
                client.Track(TrackedSource.Create(derivationStrategy));
            }

            if (address != null)
            {
                client.Track(TrackedSource.Create(address));
            }

            return(externalServiceData, null);
        }
        public async Task <string> WithdrawBtc(string withdrawHash, string recipient, decimal amount)
        {
            var coins        = new List <UTXO>();
            var coinsUsed    = new List <UTXO>();
            var estimatedFee = await client.GetFeeRateAsync(3);

            try
            {
                await locker.WaitAsync();

                while (coinsUsed.Sum(c => c.AsCoin().Amount.ToDecimal(MoneyUnit.BTC)) <= amount)
                {
                    var txOperations = await client.GetUTXOsAsync(TrackedSource.Create(pubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main)));

                    foreach (var op in txOperations.Confirmed.UTXOs)
                    {
                        if (!usedInputs.ContainsKey(op.TransactionHash.ToString() + op.Value.Satoshi.ToString()))
                        {
                            coins.Add(op);
                        }
                    }

                    coins.Sort(delegate(UTXO x, UTXO y)
                    {
                        return(-x.AsCoin().Amount.CompareTo(y.AsCoin().Amount));
                    });

                    foreach (var item in coins)
                    {
                        if (coinsUsed.Sum(c => c.AsCoin().Amount.ToDecimal(MoneyUnit.BTC)) <= amount)
                        {
                            coinsUsed.Add(item);
                            usedInputs.Add(item.TransactionHash.ToString() + item.Value.Satoshi.ToString(), item);
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (coinsUsed.Sum(c => c.AsCoin().Amount.ToDecimal(MoneyUnit.BTC)) < amount)
                    {
                        await Task.Delay(5000);
                    }
                }

                TransactionBuilder   builder     = null;
                BitcoinPubKeyAddress destination = null;
                if (network == NetworkType.Testnet)
                {
                    builder     = Network.TestNet.CreateTransactionBuilder();
                    destination = new BitcoinPubKeyAddress(recipient, Network.TestNet);
                }
                else
                {
                    builder     = Network.Main.CreateTransactionBuilder();
                    destination = new BitcoinPubKeyAddress(recipient, Network.Main);
                }

                NBitcoin.Transaction tx = builder
                                          .AddCoins(coinsUsed.Select(c => c.AsCoin() /* .ScriptPubKey.ToBytes()*/))
                                          .Send(destination, Money.Coins(amount))
                                          .Send(TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(withdrawHash)), Money.Zero)
                                          .SetChange(pubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main))
                                          .SendEstimatedFees((await client.GetFeeRateAsync(3)).FeeRate)
                                          .BuildTransaction(sign: false);

                // Specify the path to unmanaged PKCS#11 library provided by the cryptographic device vendor
                string pkcs11LibraryPath = @"/opt/cloudhsm/lib/libcloudhsm_pkcs11_standard.so";

                // Create factories used by Pkcs11Interop library
                Net.Pkcs11Interop.HighLevelAPI.Pkcs11InteropFactories factories = new Net.Pkcs11Interop.HighLevelAPI.Pkcs11InteropFactories();

                // Load unmanaged PKCS#11 library
                using (Net.Pkcs11Interop.HighLevelAPI.IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, pkcs11LibraryPath, AppType.MultiThreaded))
                {
                    // Show general information about loaded library
                    Net.Pkcs11Interop.HighLevelAPI.ILibraryInfo libraryInfo = pkcs11Library.GetInfo();

                    Console.WriteLine("Library");
                    Console.WriteLine("  Manufacturer:       " + libraryInfo.ManufacturerId);
                    Console.WriteLine("  Description:        " + libraryInfo.LibraryDescription);
                    Console.WriteLine("  Version:            " + libraryInfo.LibraryVersion);

                    // Get list of all available slots
                    foreach (Net.Pkcs11Interop.HighLevelAPI.ISlot slot in pkcs11Library.GetSlotList(SlotsType.WithOrWithoutTokenPresent))
                    {
                        // Show basic information about slot
                        Net.Pkcs11Interop.HighLevelAPI.ISlotInfo slotInfo = slot.GetSlotInfo();

                        Console.WriteLine();
                        Console.WriteLine("Slot");
                        Console.WriteLine("  Manufacturer:       " + slotInfo.ManufacturerId);
                        Console.WriteLine("  Description:        " + slotInfo.SlotDescription);
                        Console.WriteLine("  Token present:      " + slotInfo.SlotFlags.TokenPresent);

                        if (slotInfo.SlotFlags.TokenPresent)
                        {
                            // Show basic information about token present in the slot
                            Net.Pkcs11Interop.HighLevelAPI.ITokenInfo tokenInfo = slot.GetTokenInfo();

                            Console.WriteLine("Token");
                            Console.WriteLine("  Manufacturer:       " + tokenInfo.ManufacturerId);
                            Console.WriteLine("  Model:              " + tokenInfo.Model);
                            Console.WriteLine("  Serial number:      " + tokenInfo.SerialNumber);
                            Console.WriteLine("  Label:              " + tokenInfo.Label);

                            // Show list of mechanisms (algorithms) supported by the token
                            Console.WriteLine("Supported mechanisms: ");
                            foreach (CKM mechanism in slot.GetMechanismList())
                            {
                                Console.WriteLine("  " + mechanism);
                            }
                        }

                        using (Net.Pkcs11Interop.HighLevelAPI.ISession session = slot.OpenSession(SessionType.ReadWrite))
                        {
                            session.Login(CKU.CKU_USER, pkcsUser);

                            // Specify signing mechanism
                            Net.Pkcs11Interop.HighLevelAPI.IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_ECDSA);

                            List <Net.Pkcs11Interop.HighLevelAPI.IObjectAttribute> publicKeyAttributes = new List <Net.Pkcs11Interop.HighLevelAPI.IObjectAttribute>();
                            publicKeyAttributes.Add(new Net.Pkcs11Interop.HighLevelAPI80.ObjectAttribute(CKA.CKA_LABEL, hsmKey));
                            publicKeyAttributes.Add(new Net.Pkcs11Interop.HighLevelAPI80.ObjectAttribute(CKA.CKA_SIGN, true));


                            Net.Pkcs11Interop.HighLevelAPI.IObjectHandle key = session.FindAllObjects(publicKeyAttributes).FirstOrDefault();

                            uint i = 0;
                            foreach (var c in tx.Inputs.AsIndexedInputs())
                            {
                                byte[] sourceData = c.GetSignatureHash(coinsUsed.First(cu => cu.Outpoint.Hash == c.PrevOut.Hash).AsCoin()).ToBytes();
                                Console.WriteLine("sourceData: " + tx.ToHex());

                                byte[] signature = session.Sign(mechanism, key, sourceData);
                                Console.WriteLine("signature: " + BitConverter.ToString(signature));
                                var canSig = ECDSASignatureFactory.FromComponents(signature).MakeCanonical();
                                var sig    = new NBitcoin.TransactionSignature(new NBitcoin.Crypto.ECDSASignature(new NBitcoin.BouncyCastle.Math.BigInteger(canSig.R.ToByteArray()), new NBitcoin.BouncyCastle.Math.BigInteger(canSig.S.ToByteArray())), SigHash.Single);
                                builder = builder.AddKnownSignature(pubKey, sig, c.PrevOut);
                                TransactionSignature sig2 = null;
                                if (builder.TrySignInput(tx, i, SigHash.Single, out sig2))
                                {
                                    Console.WriteLine("Input Signed");
                                    Console.WriteLine(BitConverter.ToString(sig2.ToBytes()));
                                }
                                else
                                {
                                    Console.WriteLine("Input Not Signed");
                                }

                                Console.WriteLine("tx: " + tx);
                                i++;

                                tx = builder.SignTransactionInPlace(tx);
                            }


                            Console.WriteLine("tx: " + tx);
                            TransactionPolicyError[] errors = null;
                            if (builder.Verify(tx, out errors))
                            {
                                var broadcastResult = await client.BroadcastAsync(tx);

                                broadcastResult.ToString();
                                Console.WriteLine("broadcast: " + tx.GetHash().ToString());
                                session.Logout();
                                return(tx.GetHash().ToString());
                            }
                            else
                            {
                                Console.WriteLine("Verify transaction failed");
                            }

                            if (errors != null)
                            {
                                foreach (var e in errors)
                                {
                                    Console.WriteLine(e.ToString());
                                }
                            }

                            session.Logout();
                        }
                    }
                }

                return(null);
            }
            catch (Exception e)
            {
                Log.Error("Failed to send BTC Withdraw" + e.ToString());
                throw e;
            }
            finally
            {
                locker.Release();
            }
        }
Beispiel #14
0
        public async Task <WithdrawInfo> WithdrawBtc(string withdrawHash, string recipient, decimal amount)
        {
            var txOperations = await client.GetUTXOsAsync(TrackedSource.Create(wallet.GetAddress()));

            var coins = new List <Coin>();

            foreach (var op in txOperations.Confirmed.UTXOs)
            {
                coins.Add(op.AsCoin());
            }

            coins.Sort(delegate(Coin x, Coin y)
            {
                return(-x.Amount.CompareTo(y.Amount));
            });

            var coinSum = 0m;

            for (int i = 0; coinSum < amount; i++)
            {
                coinSum += coins[i].Amount.ToDecimal(MoneyUnit.BTC);
                if (coinSum >= amount)
                {
                    coins.RemoveRange(i + 1, coins.Count - (i + 1));
                }
            }

            TransactionBuilder   builder     = null;
            BitcoinPubKeyAddress destination = null;

            if (network == NetworkType.Testnet)
            {
                builder     = Network.TestNet.CreateTransactionBuilder();
                destination = new BitcoinPubKeyAddress(recipient, Network.TestNet);
            }
            else
            {
                builder     = Network.Main.CreateTransactionBuilder();
                destination = new BitcoinPubKeyAddress(recipient, Network.Main);
            }
            NBitcoin.Transaction tx = builder
                                      .AddCoins(coins)
                                      .AddKeys(wallet)
                                      .Send(destination, Money.Coins(amount))
                                      .Send(TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(withdrawHash)), Money.Zero)
                                      .SetChange(wallet)
                                      .SendFees(Money.Coins(0.0001m))
                                      .BuildTransaction(sign: true);

            TransactionPolicyError[] errors = null;
            if (builder.Verify(tx, out errors))
            {
                var broadcastResult = await client.BroadcastAsync(tx);

                broadcastResult.ToString();
                return(new WithdrawInfo()
                {
                    TxHash = tx.GetHash().ToString(), Timestamp = DateTime.Now
                });
            }

            if (errors != null)
            {
                errors.ToString();
            }

            return(null);
        }
Beispiel #15
0
        public async Task <NBXplorerPublicWallet> Get(string cryptoCode, DerivationStrategyBase derivationStrategyBase)
        {
            var key = $"{cryptoCode}:{derivationStrategyBase}";

            if (_wallets.ContainsKey(key))
            {
                return(_wallets[key]);
            }
            _wallets.Add(key, new NBXplorerPublicWallet(_clientProvider.GetClient(cryptoCode), TrackedSource.Create(derivationStrategyBase)));
            return(await Get(cryptoCode, derivationStrategyBase));
        }
Beispiel #16
0
        public async Task <NBXplorerPublicWallet> Get(string cryptoCode, BitcoinAddress address)
        {
            var key = $"{cryptoCode}:{address}";

            if (_wallets.ContainsKey(key))
            {
                return(_wallets[key]);
            }
            _wallets.Add(key, new NBXplorerPublicWallet(_clientProvider.GetClient(cryptoCode), TrackedSource.Create(address)));
            return(await Get(cryptoCode, address));
        }