コード例 #1
0
        public async Task <ActionResult> Index(string search = null, int count = 5)
        {
            count = Math.Max(0, count);
            count = Math.Min(50, count);
            if (!string.IsNullOrWhiteSpace(search))
            {
                search = search.Trim();
                if (search.StartsWith("0x") || search.Contains("OP_"))
                {
                    return(RedirectToAction("Address", new
                    {
                        address = search
                    }));
                }
                try
                {
                    BitcoinAddress.Create(search, QBit.Network);
                    return(RedirectToAction("Address", new
                    {
                        address = search
                    }));
                }
                catch { }

                if (search.Length == 32 * 2)
                {
                    if (search.StartsWith("0000000000"))
                    {
                        return(RedirectToAction("Block", new
                        {
                            blockFeature = search
                        }));
                    }
                    else
                    {
                        return(RedirectToAction("Transaction", new
                        {
                            txId = search
                        }));
                    }
                }

                try
                {
                    BlockFeature.Parse(search);
                    return(RedirectToAction("Block", new
                    {
                        blockFeature = search
                    }));
                }
                catch { }
                return(View());
            }

            var responses =
                await Task.WhenAll(Enumerable
                                   .Range(0, count)
                                   .Select(i => QBit.GetBlock(new BlockFeature(SpecialFeature.Last)
            {
                Offset = -i
            }, true, true))
                                   .ToArray());

            var model = new MainModel();

            model.NextCount = count + 5;
            foreach (var response in responses.Where(r => r.ExtendedInformation != null && r.AdditionalInformation != null))
            {
                var blockModel = new MainBlockModel();
                blockModel.Hash              = response.AdditionalInformation.BlockId;
                blockModel.Height            = response.AdditionalInformation.Height;
                blockModel.Size              = ToKB(response.ExtendedInformation.Size);
                blockModel.Time              = ToRelative(response.AdditionalInformation.BlockTime);
                blockModel.TransactionsCount = response.ExtendedInformation.TransactionCount;
                blockModel.Fees              = ToString(response.ExtendedInformation.BlockReward - response.ExtendedInformation.BlockSubsidy);
                model.Blocks.Add(blockModel);
            }
            return(View(model));
        }
コード例 #2
0
ファイル: TestUtils.cs プロジェクト: shanecelis/NBitcoin
 public static Transaction CreateFakeTx(Money coin, BitcoinAddress to)
 {
     return(CreateFakeTx(coin, (KeyId)to.Hash));
 }
コード例 #3
0
        private List <TransactionInformation> QueryWithListReceivedByAddress(bool withProof, BitcoinAddress address)
        {
            var result       = RPCClient.SendCommand("listreceivedbyaddress", 0, false, true, address.ToString());
            var transactions = ((JArray)result.Result).OfType <JObject>().Select(o => o["txids"]).OfType <JArray>().SingleOrDefault();

            if (transactions == null)
            {
                return(null);
            }

            HashSet <uint256>             resultsSet = new HashSet <uint256>();
            List <TransactionInformation> results    = new List <TransactionInformation>();

            foreach (var txIdObj in transactions)
            {
                var txId = new uint256(txIdObj.ToString());
                //May have duplicates
                if (!resultsSet.Contains(txId))
                {
                    var tx = GetTransaction(txId);
                    if (tx == null || (withProof && tx.Confirmations == 0))
                    {
                        continue;
                    }
                    resultsSet.Add(txId);
                    results.Add(tx);
                }
            }
            return(results);
        }
コード例 #4
0
        public async Task <IActionResult> AddDerivationScheme(string storeId, DerivationSchemeViewModel vm,
                                                              string cryptoCode)
        {
            vm.CryptoCode = cryptoCode;
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(NotFound());
            }

            var network = cryptoCode == null ? null : _ExplorerProvider.GetNetwork(cryptoCode);

            if (network == null)
            {
                return(NotFound());
            }

            vm.Network     = network;
            vm.RootKeyPath = network.GetRootKeyPath();
            DerivationSchemeSettings strategy = null;

            var wallet = _WalletProvider.GetWallet(network);

            if (wallet == null)
            {
                return(NotFound());
            }

            if (!string.IsNullOrEmpty(vm.Config))
            {
                if (!DerivationSchemeSettings.TryParseFromJson(vm.Config, network, out strategy))
                {
                    TempData.SetStatusMessageModel(new StatusMessageModel()
                    {
                        Severity = StatusMessageModel.StatusSeverity.Error,
                        Message  = "Config file was not in the correct format"
                    });
                    vm.Confirmation = false;
                    return(View(vm));
                }
            }

            if (vm.ColdcardPublicFile != null)
            {
                if (!DerivationSchemeSettings.TryParseFromColdcard(await ReadAllText(vm.ColdcardPublicFile), network, out strategy))
                {
                    TempData.SetStatusMessageModel(new StatusMessageModel()
                    {
                        Severity = StatusMessageModel.StatusSeverity.Error,
                        Message  = "Coldcard public file was not in the correct format"
                    });
                    vm.Confirmation = false;
                    return(View(vm));
                }
            }
            else
            {
                try
                {
                    if (!string.IsNullOrEmpty(vm.DerivationScheme))
                    {
                        var newStrategy = ParseDerivationStrategy(vm.DerivationScheme, null, network);
                        if (newStrategy.AccountDerivation != strategy?.AccountDerivation)
                        {
                            var accountKey = string.IsNullOrEmpty(vm.AccountKey) ? null : new BitcoinExtPubKey(vm.AccountKey, network.NBitcoinNetwork);
                            if (accountKey != null)
                            {
                                var accountSettings = newStrategy.AccountKeySettings.FirstOrDefault(a => a.AccountKey == accountKey);
                                if (accountSettings != null)
                                {
                                    accountSettings.AccountKeyPath  = vm.KeyPath == null ? null : KeyPath.Parse(vm.KeyPath);
                                    accountSettings.RootFingerprint = string.IsNullOrEmpty(vm.RootFingerprint) ? (HDFingerprint?)null : new HDFingerprint(NBitcoin.DataEncoders.Encoders.Hex.DecodeData(vm.RootFingerprint));
                                }
                            }
                            strategy            = newStrategy;
                            strategy.Source     = vm.Source;
                            vm.DerivationScheme = strategy.AccountDerivation.ToString();
                        }
                    }
                    else
                    {
                        strategy = null;
                    }
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                    vm.Confirmation = false;
                    return(View(vm));
                }
            }

            var oldConfig = vm.Config;

            vm.Config = strategy == null ? null : strategy.ToJson();

            PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
            var             exisingStrategy = store.GetSupportedPaymentMethods(_NetworkProvider)
                                              .Where(c => c.PaymentId == paymentMethodId)
                                              .OfType <DerivationSchemeSettings>()
                                              .FirstOrDefault();
            var storeBlob      = store.GetStoreBlob();
            var wasExcluded    = storeBlob.GetExcludedPaymentMethods().Match(paymentMethodId);
            var willBeExcluded = !vm.Enabled;

            var showAddress = // Show addresses if:
                              // - If the user is testing the hint address in confirmation screen
                              (vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress)) ||
                              // - The user is clicking on continue after changing the config
                              (!vm.Confirmation && oldConfig != vm.Config) ||
                              // - The user is clickingon continue without changing config nor enabling/disabling
                              (!vm.Confirmation && oldConfig == vm.Config && willBeExcluded == wasExcluded);

            showAddress = showAddress && strategy != null;
            if (!showAddress)
            {
                try
                {
                    if (strategy != null)
                    {
                        await wallet.TrackAsync(strategy.AccountDerivation);
                    }
                    store.SetSupportedPaymentMethod(paymentMethodId, strategy);
                    storeBlob.SetExcluded(paymentMethodId, willBeExcluded);
                    store.SetStoreBlob(storeBlob);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.DerivationScheme), "Invalid Derivation Scheme");
                    return(View(vm));
                }

                await _Repo.UpdateStore(store);

                if (willBeExcluded != wasExcluded)
                {
                    var label = willBeExcluded ? "disabled" : "enabled";
                    TempData[WellKnownTempData.SuccessMessage] = $"On-Chain payments for {network.CryptoCode} has been {label}.";
                }
                else
                {
                    TempData[WellKnownTempData.SuccessMessage] = $"Derivation settings for {network.CryptoCode} has been modified.";
                }
                return(RedirectToAction(nameof(UpdateStore), new { storeId = storeId }));
            }
            else if (!string.IsNullOrEmpty(vm.HintAddress))
            {
                BitcoinAddress address = null;
                try
                {
                    address = BitcoinAddress.Create(vm.HintAddress, network.NBitcoinNetwork);
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Invalid hint address");
                    return(ShowAddresses(vm, strategy));
                }

                try
                {
                    var newStrategy = ParseDerivationStrategy(vm.DerivationScheme, address.ScriptPubKey, network);
                    if (newStrategy.AccountDerivation != strategy.AccountDerivation)
                    {
                        strategy.AccountDerivation = newStrategy.AccountDerivation;
                        strategy.AccountOriginal   = null;
                    }
                }
                catch
                {
                    ModelState.AddModelError(nameof(vm.HintAddress), "Impossible to find a match with this address");
                    return(ShowAddresses(vm, strategy));
                }

                vm.HintAddress = "";
                TempData[WellKnownTempData.SuccessMessage] =
                    "Address successfully found, please verify that the rest is correct and click on \"Confirm\"";
                ModelState.Remove(nameof(vm.HintAddress));
                ModelState.Remove(nameof(vm.DerivationScheme));
            }

            return(ShowAddresses(vm, strategy));
        }
コード例 #5
0
ファイル: RPCClient.cs プロジェクト: hu53yin/NBitcoin
		public async Task<BitcoinSecret> DumpPrivKeyAsync(BitcoinAddress address)
		{
			var response = await SendCommandAsync("dumpprivkey", address.ToString()).ConfigureAwait(false);
			return Network.CreateFromBase58Data<BitcoinSecret>((string)response.Result);
		}
コード例 #6
0
ファイル: util_tests.cs プロジェクト: woutersmit/NBitcoin
		//https://en.bitcoin.it/wiki/List_of_address_prefixes
		public void CanDeduceNetworkInBase58Constructor()
		{
			BitcoinAddress addr = new BitcoinAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem");
			Assert.Equal(addr.Network, Network.Main);
		}
コード例 #7
0
ファイル: base58_tests.cs プロジェクト: FluidChains/FullNode
        public void base58_keys_valid_gen()
        {
            TestCase[] tests = TestCase.read_json(TestDataLocations.GetFileFromDataFolder("base58_keys_valid.json"));
            tests = tests.Concat(TestCase.read_json(TestDataLocations.GetFileFromDataFolder("base58_keys_valid2.json"))).ToArray();
            Network network = null;

            foreach (TestCase test in tests)
            {
                string strTest = test.ToString();
                if (test.Count < 3) // Allow for extra stuff (useful for comments)
                {
                    Assert.False(true, "Bad test: " + strTest);
                    continue;
                }
                string  exp_base58string = (string)test[0];
                byte[]  exp_payload      = TestUtils.ParseHex((string)test[1]);
                dynamic metadata         = test.GetDynamic(2);
                bool    isPrivkey        = (bool)metadata.isPrivkey;
                bool    isTestnet        = (bool)metadata.isTestnet;

                if (isTestnet)
                {
                    network = KnownNetworks.TestNet;
                }
                else
                {
                    network = KnownNetworks.Main;
                }
                if (isPrivkey)
                {
                    bool          isCompressed = metadata.isCompressed;
                    var           key          = new Key(exp_payload, fCompressedIn: isCompressed);
                    BitcoinSecret secret       = network.CreateBitcoinSecret(key);
                    Assert.True(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
                }
                else
                {
                    string        exp_addrType = (string)metadata.addrType;
                    TxDestination dest;
                    if (exp_addrType == "pubkey")
                    {
                        dest = new KeyId(new uint160(exp_payload));
                    }
                    else if (exp_addrType == "script")
                    {
                        dest = new ScriptId(new uint160(exp_payload));
                    }
                    else if (exp_addrType == "p2wpkh")
                    {
                        dest = new WitKeyId(new uint160(exp_payload));
                    }
                    else if (exp_addrType == "p2wsh")
                    {
                        dest = new WitScriptId(exp_payload);
                    }
                    else if (exp_addrType == "none")
                    {
                        continue;
                    }
                    else
                    {
                        Assert.True(false, "Bad addrtype: " + strTest);
                        continue;
                    }
                    try
                    {
                        BitcoinAddress addrOut = dest.GetAddress(network);
                        Assert.True(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
                        Assert.True(addrOut.ScriptPubKey == dest.ScriptPubKey);
                        Assert.True(dest.ScriptPubKey.GetDestination(KnownNetworks.Main) == dest);
                    }
                    catch (ArgumentException)
                    {
                        Assert.True(dest.GetType() == typeof(TxDestination));
                    }
                }
            }
        }
コード例 #8
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		public void ImportAddress(BitcoinAddress address, string label, bool rescan)
		{
			SendCommand("importaddress", address.ToString(), label, rescan);
		}
コード例 #9
0
 /// <summary>
 /// Take the first four bytes of SHA256(SHA256(generatedaddress)) and call it addresshash.
 /// </summary>
 /// <param name="address"></param>
 /// <returns></returns>
 internal static byte[] HashAddress(BitcoinAddress address)
 {
     return(Hashes.Hash256(Encoders.ASCII.DecodeData(address.ToString())).ToBytes().Take(4).ToArray());
 }
コード例 #10
0
        public void CanComputeCrowdfundModel()
        {
            using (var tester = ServerTester.Create())
            {
                tester.Start();
                var user = tester.NewAccount();
                user.GrantAccess();
                user.RegisterDerivationScheme("BTC");
                user.ModifyStore(s => s.NetworkFeeMode = NetworkFeeMode.Never);
                var apps = user.GetController <AppsController>();
                var vm   = Assert.IsType <CreateAppViewModel>(Assert.IsType <ViewResult>(apps.CreateApp().Result).Model);
                vm.Name            = "test";
                vm.SelectedAppType = AppType.Crowdfund.ToString();
                Assert.IsType <RedirectToActionResult>(apps.CreateApp(vm).Result);
                var appId = Assert.IsType <ListAppsViewModel>(Assert.IsType <ViewResult>(apps.ListApps().Result).Model)
                            .Apps[0].Id;

                Logs.Tester.LogInformation("We create an invoice with a hardcap");
                var crowdfundViewModel = Assert.IsType <UpdateCrowdfundViewModel>(Assert
                                                                                  .IsType <ViewResult>(apps.UpdateCrowdfund(appId).Result).Model);
                crowdfundViewModel.Enabled             = true;
                crowdfundViewModel.EndDate             = null;
                crowdfundViewModel.TargetAmount        = 100;
                crowdfundViewModel.TargetCurrency      = "BTC";
                crowdfundViewModel.UseAllStoreInvoices = true;
                crowdfundViewModel.EnforceTargetAmount = true;
                Assert.IsType <RedirectToActionResult>(apps.UpdateCrowdfund(appId, crowdfundViewModel).Result);

                var anonAppPubsController = tester.PayTester.GetController <AppsPublicController>();
                var publicApps            = user.GetController <AppsPublicController>();

                var model = Assert.IsType <ViewCrowdfundViewModel>(Assert
                                                                   .IsType <ViewResult>(publicApps.ViewCrowdfund(appId, String.Empty).Result).Model);


                Assert.Equal(crowdfundViewModel.TargetAmount, model.TargetAmount);
                Assert.Equal(crowdfundViewModel.EndDate, model.EndDate);
                Assert.Equal(crowdfundViewModel.StartDate, model.StartDate);
                Assert.Equal(crowdfundViewModel.TargetCurrency, model.TargetCurrency);
                Assert.Equal(0m, model.Info.CurrentAmount);
                Assert.Equal(0m, model.Info.CurrentPendingAmount);
                Assert.Equal(0m, model.Info.ProgressPercentage);


                Logs.Tester.LogInformation("Unpaid invoices should show as pending contribution because it is hardcap");
                Logs.Tester.LogInformation("Because UseAllStoreInvoices is true, we can manually create an invoice and it should show as contribution");
                var invoice = user.BitPay.CreateInvoice(new Invoice()
                {
                    Buyer = new Buyer()
                    {
                        email = "*****@*****.**"
                    },
                    Price             = 1m,
                    Currency          = "BTC",
                    PosData           = "posData",
                    ItemDesc          = "Some description",
                    TransactionSpeed  = "high",
                    FullNotifications = true
                }, Facade.Merchant);


                model = Assert.IsType <ViewCrowdfundViewModel>(Assert
                                                               .IsType <ViewResult>(publicApps.ViewCrowdfund(appId, String.Empty).Result).Model);

                Assert.Equal(0m, model.Info.CurrentAmount);
                Assert.Equal(1m, model.Info.CurrentPendingAmount);
                Assert.Equal(0m, model.Info.ProgressPercentage);
                Assert.Equal(1m, model.Info.PendingProgressPercentage);

                Logs.Tester.LogInformation("Let's check current amount change once payment is confirmed");
                var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, tester.ExplorerNode.Network);
                tester.ExplorerNode.SendToAddress(invoiceAddress, invoice.BtcDue);
                tester.ExplorerNode.Generate(1); // By default invoice confirmed at 1 block
                TestUtils.Eventually(() =>
                {
                    model = Assert.IsType <ViewCrowdfundViewModel>(Assert
                                                                   .IsType <ViewResult>(publicApps.ViewCrowdfund(appId, String.Empty).Result).Model);
                    Assert.Equal(1m, model.Info.CurrentAmount);
                    Assert.Equal(0m, model.Info.CurrentPendingAmount);
                });

                Logs.Tester.LogInformation("Because UseAllStoreInvoices is true, let's make sure the invoice is tagged");
                var invoiceEntity = tester.PayTester.InvoiceRepository.GetInvoice(invoice.Id).GetAwaiter().GetResult();
                Assert.True(invoiceEntity.Version >= InvoiceEntity.InternalTagSupport_Version);
                Assert.Contains(AppService.GetAppInternalTag(appId), invoiceEntity.InternalTags);

                crowdfundViewModel.UseAllStoreInvoices = false;
                Assert.IsType <RedirectToActionResult>(apps.UpdateCrowdfund(appId, crowdfundViewModel).Result);

                Logs.Tester.LogInformation("Because UseAllStoreInvoices is false, let's make sure the invoice is not tagged");
                invoice = user.BitPay.CreateInvoice(new Invoice()
                {
                    Buyer = new Buyer()
                    {
                        email = "*****@*****.**"
                    },
                    Price             = 1m,
                    Currency          = "BTC",
                    PosData           = "posData",
                    ItemDesc          = "Some description",
                    TransactionSpeed  = "high",
                    FullNotifications = true
                }, Facade.Merchant);
                invoiceEntity = tester.PayTester.InvoiceRepository.GetInvoice(invoice.Id).GetAwaiter().GetResult();
                Assert.DoesNotContain(AppService.GetAppInternalTag(appId), invoiceEntity.InternalTags);

                Logs.Tester.LogInformation("After turning setting a softcap, let's check that only actual payments are counted");
                crowdfundViewModel.EnforceTargetAmount = false;
                crowdfundViewModel.UseAllStoreInvoices = true;
                Assert.IsType <RedirectToActionResult>(apps.UpdateCrowdfund(appId, crowdfundViewModel).Result);
                invoice = user.BitPay.CreateInvoice(new Invoice()
                {
                    Buyer = new Buyer()
                    {
                        email = "*****@*****.**"
                    },
                    Price             = 1m,
                    Currency          = "BTC",
                    PosData           = "posData",
                    ItemDesc          = "Some description",
                    TransactionSpeed  = "high",
                    FullNotifications = true
                }, Facade.Merchant);
                Assert.Equal(0m, model.Info.CurrentPendingAmount);
                invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, tester.ExplorerNode.Network);
                tester.ExplorerNode.SendToAddress(invoiceAddress, Money.Coins(0.5m));
                tester.ExplorerNode.SendToAddress(invoiceAddress, Money.Coins(0.2m));
                TestUtils.Eventually(() =>
                {
                    model = Assert.IsType <ViewCrowdfundViewModel>(Assert
                                                                   .IsType <ViewResult>(publicApps.ViewCrowdfund(appId, String.Empty).Result).Model);
                    Assert.Equal(0.7m, model.Info.CurrentPendingAmount);
                });
            }
        }
コード例 #11
0
        protected SendControlViewModel(Wallet wallet, string title)
            : base(title)
        {
            Global = Locator.Current.GetService <Global>();
            Wallet = wallet;

            LabelSuggestion            = new SuggestLabelViewModel();
            BuildTransactionButtonText = DoButtonText;

            ResetUi();
            SetAmountWatermark(Money.Zero);

            CoinList = new CoinListViewModel(Wallet, displayCommonOwnershipWarning: true);

            Observable.FromEventPattern(CoinList, nameof(CoinList.SelectionChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => SetFeesAndTexts());

            _minMaxFeeTargetsEqual = this.WhenAnyValue(x => x.MinimumFeeTarget, x => x.MaximumFeeTarget, (x, y) => x == y)
                                     .ToProperty(this, x => x.MinMaxFeeTargetsEqual, scheduler: RxApp.MainThreadScheduler);

            SetFeeTargetLimits();
            FeeTarget        = Global.UiConfig.FeeTarget;
            FeeDisplayFormat = (FeeDisplayFormat)(Enum.ToObject(typeof(FeeDisplayFormat), Global.UiConfig.FeeDisplayFormat) ?? FeeDisplayFormat.SatoshiPerByte);
            SetFeesAndTexts();

            this.WhenAnyValue(x => x.AmountText)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (Money.TryParse(x.TrimStart('~', ' '), out Money amountBtc))
                {
                    SetAmountWatermark(amountBtc);
                }
                else
                {
                    SetAmountWatermark(Money.Zero);
                }

                SetFees();
            });

            AmountKeyUpCommand = ReactiveCommand.Create((KeyEventArgs key) =>
            {
                var amount = AmountText;
                if (IsMax)
                {
                    SetFeesAndTexts();
                }
                else
                {
                    // Correct amount
                    Regex digitsOnly    = new Regex(@"[^\d,.]");
                    string betterAmount = digitsOnly.Replace(amount, "");                     // Make it digits , and . only.

                    betterAmount          = betterAmount.Replace(',', '.');
                    int countBetterAmount = betterAmount.Count(x => x == '.');
                    if (countBetterAmount > 1)                     // Do not enable typing two dots.
                    {
                        var index = betterAmount.IndexOf('.', betterAmount.IndexOf('.') + 1);
                        if (index > 0)
                        {
                            betterAmount = betterAmount.Substring(0, index);
                        }
                    }
                    var dotIndex = betterAmount.IndexOf('.');
                    if (dotIndex != -1 && betterAmount.Length - dotIndex > 8)                     // Enable max 8 decimals.
                    {
                        betterAmount = betterAmount.Substring(0, dotIndex + 1 + 8);
                    }

                    if (betterAmount != amount)
                    {
                        AmountText = betterAmount;
                    }
                }
            });

            this.WhenAnyValue(x => x.IsBusy, x => x.IsHardwareBusy)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => BuildTransactionButtonText = IsHardwareBusy
                                                ? WaitingForHardwareWalletButtonTextString
                                                : IsBusy
                                                        ? DoingButtonText
                                                        : DoButtonText);

            this.WhenAnyValue(x => x.FeeTarget)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                IsSliderFeeUsed = true;
                SetFeesAndTexts();
            });

            this.WhenAnyValue(x => x.IsSliderFeeUsed)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(enabled => FeeControlOpacity = enabled ? 1 : 0.5);                     // Give the control the disabled feeling. Real Disable it not a solution as we have to detect if the slider is moved.

            MaxCommand = ReactiveCommand.Create(() => IsMax = !IsMax, outputScheduler: RxApp.MainThreadScheduler);

            this.WhenAnyValue(x => x.IsMax)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                if (IsMax)
                {
                    SetFeesAndTexts();

                    LabelToolTip = "Spending whole coins does not generate change, thus labeling is unnecessary.";
                }
                else
                {
                    AmountText = "0.0";

                    LabelToolTip = "Who can link this transaction to you? E.g.: \"Max, BitPay\"";
                }
            });

            // Triggering the detection of same address values.
            this.WhenAnyValue(x => x.Address)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => this.RaisePropertyChanged(nameof(CustomChangeAddress)));

            this.WhenAnyValue(x => x.CustomChangeAddress)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => this.RaisePropertyChanged(nameof(Address)));

            FeeRateCommand = ReactiveCommand.Create(ChangeFeeRateDisplay, outputScheduler: RxApp.MainThreadScheduler);

            OnAddressPasteCommand = ReactiveCommand.Create((BitcoinUrlBuilder url) =>
            {
                SmartLabel label = url.Label;
                if (!label.IsEmpty)
                {
                    LabelSuggestion.Label = label;
                }

                if (url.Amount != null)
                {
                    AmountText = url.Amount.ToString(false, true);
                }
            });

            BuildTransactionCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                try
                {
                    IsBusy = true;
                    MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.BuildingTransaction);

                    var label             = new SmartLabel(LabelSuggestion.Label);
                    LabelSuggestion.Label = label;
                    if (!IsMax && label.IsEmpty)
                    {
                        NotificationHelpers.Warning("Observers are required.", "");
                        return;
                    }

                    var selectedCoinViewModels = CoinList.Coins.Where(cvm => cvm.IsSelected);
                    var selectedCoinReferences = selectedCoinViewModels.Select(cvm => cvm.Model.OutPoint).ToList();

                    if (!selectedCoinReferences.Any())
                    {
                        NotificationHelpers.Warning("No coins are selected to spend.", "");
                        return;
                    }

                    BitcoinAddress address;
                    try
                    {
                        address = BitcoinAddress.Create(Address, Global.Network);
                    }
                    catch (FormatException)
                    {
                        NotificationHelpers.Warning("Invalid address.", "");
                        return;
                    }

                    var requests = new List <DestinationRequest>();

                    if (Global.UiConfig.IsCustomChangeAddress && !IsMax && !string.IsNullOrWhiteSpace(CustomChangeAddress))
                    {
                        try
                        {
                            var customChangeAddress = BitcoinAddress.Create(CustomChangeAddress, Global.Network);

                            if (customChangeAddress == address)
                            {
                                NotificationHelpers.Warning("The active address and the change address cannot be the same.", "");
                                return;
                            }

                            requests.Add(new DestinationRequest(customChangeAddress, MoneyRequest.CreateChange(subtractFee: true), label));
                        }
                        catch (FormatException)
                        {
                            NotificationHelpers.Warning("Invalid custom change address.", "");
                            return;
                        }
                    }

                    MoneyRequest moneyRequest;
                    if (IsMax)
                    {
                        moneyRequest = MoneyRequest.CreateAllRemaining(subtractFee: true);
                    }
                    else
                    {
                        if (!Money.TryParse(AmountText, out Money amount) || amount == Money.Zero)
                        {
                            NotificationHelpers.Warning("Invalid amount.");
                            return;
                        }

                        if (amount == selectedCoinViewModels.Sum(x => x.Amount))
                        {
                            NotificationHelpers.Warning("Looks like you want to spend whole coins. Try Max button instead.", "");
                            return;
                        }
                        moneyRequest = MoneyRequest.Create(amount, subtractFee: false);
                    }

                    if (FeeRate is null || FeeRate.SatoshiPerByte < 1)
                    {
                        NotificationHelpers.Warning("Invalid fee rate.", "");
                        return;
                    }

                    var feeStrategy = FeeStrategy.CreateFromFeeRate(FeeRate);

                    var activeDestinationRequest = new DestinationRequest(address, moneyRequest, label);
                    requests.Add(activeDestinationRequest);

                    var intent = new PaymentIntent(requests);
                    try
                    {
                        MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.DequeuingSelectedCoins);
                        OutPoint[] toDequeue = selectedCoinViewModels.Where(x => x.CoinJoinInProgress).Select(x => x.Model.OutPoint).ToArray();
                        if (toDequeue != null && toDequeue.Any())
                        {
                            await Wallet.ChaumianClient.DequeueCoinsFromMixAsync(toDequeue, DequeueReason.TransactionBuilding);
                        }
                    }
                    catch
                    {
                        NotificationHelpers.Error("Cannot spend mixing coins.", "");
                        return;
                    }
                    finally
                    {
                        MainWindowViewModel.Instance.StatusBar.TryRemoveStatus(StatusType.DequeuingSelectedCoins);
                    }

                    if (!Wallet.KeyManager.IsWatchOnly)
                    {
                        try
                        {
                            PasswordHelper.GetMasterExtKey(Wallet.KeyManager, Password, out string compatiblityPasswordUsed);                             // We could use TryPassword but we need the exception.
                            if (compatiblityPasswordUsed != null)
                            {
                                Password = compatiblityPasswordUsed;                                 // Overwrite the password for BuildTransaction function.
                                NotificationHelpers.Warning(PasswordHelper.CompatibilityPasswordWarnMessage);
                            }
                        }
                        catch (SecurityException ex)
                        {
                            NotificationHelpers.Error(ex.Message, "");
                            return;
                        }
                        catch (Exception ex)
                        {
                            Logger.LogError(ex);
                            NotificationHelpers.Error(ex.ToUserFriendlyString());
                            return;
                        }
                    }

                    BuildTransactionResult result = await Task.Run(() => Wallet.BuildTransaction(Password, intent, feeStrategy, allowUnconfirmed: true, allowedInputs: selectedCoinReferences));

                    await DoAfterBuildTransaction(result);
                }
                catch (InsufficientBalanceException ex)
                {
                    Money needed = ex.Minimum - ex.Actual;
                    NotificationHelpers.Error($"Not enough coins selected. You need an estimated {needed.ToString(false, true)} BTC more to make this transaction.", "");
                }
                catch (HttpRequestException ex)
                {
                    NotificationHelpers.Error(ex.ToUserFriendlyString());
                    Logger.LogError(ex);
                }
                catch (Exception ex)
                {
                    NotificationHelpers.Error(ex.ToUserFriendlyString(), sender: Wallet);
                    Logger.LogError(ex);
                }
                finally
                {
                    MainWindowViewModel.Instance.StatusBar.TryRemoveStatus(StatusType.BuildingTransaction, StatusType.SigningTransaction, StatusType.BroadcastingTransaction);
                    IsBusy = false;
                }
            },
                                                                     this.WhenAny(x => x.IsMax, x => x.AmountText, x => x.Address, x => x.IsBusy,
                                                                                  (isMax, amount, address, busy) => (isMax.Value || !string.IsNullOrWhiteSpace(amount.Value)) && !string.IsNullOrWhiteSpace(Address) && !IsBusy)
                                                                     .ObserveOn(RxApp.MainThreadScheduler));

            UserFeeTextKeyUpCommand = ReactiveCommand.Create((KeyEventArgs key) =>
            {
                IsSliderFeeUsed = !IsCustomFee;
                SetFeesAndTexts();
            });

            FeeSliderClickedCommand = ReactiveCommand.Create((PointerPressedEventArgs mouse) => IsSliderFeeUsed = true);

            HighLightFeeSliderCommand = ReactiveCommand.Create((bool entered) =>
            {
                if (IsSliderFeeUsed)
                {
                    return;
                }

                FeeControlOpacity = entered ? 0.8 : 0.5;
            });

            Observable
            .Merge(MaxCommand.ThrownExceptions)
            .Merge(FeeRateCommand.ThrownExceptions)
            .Merge(OnAddressPasteCommand.ThrownExceptions)
            .Merge(BuildTransactionCommand.ThrownExceptions)
            .Merge(UserFeeTextKeyUpCommand.ThrownExceptions)
            .Merge(FeeSliderClickedCommand.ThrownExceptions)
            .Merge(HighLightFeeSliderCommand.ThrownExceptions)
            .Merge(AmountKeyUpCommand.ThrownExceptions)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(ex =>
            {
                NotificationHelpers.Error(ex.ToUserFriendlyString());
                Logger.LogError(ex);
            });
        }
コード例 #12
0
        public void CanVerifySignature()
        {
            var tests = new[]
            {
                new
                {
                    Address    = "15jZVzLc9cXz5PUFFda5A4Z7kZDYPg2NnL",
                    PrivateKey = "L3TiCqmvPkXJpzCCZJuhy6wQtJZWDkR1AuqFY4Utib5J5XLuvLdZ",
                    Message    = "This is an example of a signed message.",
                    Signature  = "H6sliOnVrD9r+J8boZAKHZwBIW2zLiD72IfTIF94bfZhBI0JdMu9AM9rrF7P6eH+866YvM4H9xWGVN4jMJZycFU="
                },
                new
                {
                    Address    = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ",
                    PrivateKey = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj",
                    Message    = "hello world",
                    Signature  = "G+dnSEywl3v1ijlWXvpY6zpu+AKNNXJcVmrdE35m0mMlzwFzXDiNg+uZrG9k8mpQL6sjHKrlBoDNSA+yaPW7PEA="
                },
                new
                {
                    Address    = "1Q1wVsNNiUo68caU7BfyFFQ8fVBqxC2DSc",
                    PrivateKey = null as string,
                    Message    = "Localbitcoins.com will change the world",
                    Signature  = "IJ/17TjGGUqmEppAliYBUesKHoHzfY4gR4DW0Yg7QzrHUB5FwX1uTJ/H21CF8ncY8HHNB5/lh8kPAOeD5QxV8Xc="
                },
                new
                {
                    Address    = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "This is an example of a signed message2",
                    Signature  = "G8YNwlo+I36Ct+hZKGSBFl3q8Kbx1pxPpwQmwdsG85io76+DUOHXqh/DfBq+Cn2R3C3dI//g3koSjxy7yNxJ9m8="
                },
                new
                {
                    Address    = "1GvPJp7H8UYsYDvE4GFoV4f2gSCNZzGF48",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
                    Signature  = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
                },
                new
                {
                    Address    = "bc1q463gmsagg5u8wvqqcqj92yytt0pmevvg39h9jp",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
                    Signature  = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
                },
                new
                {
                    // p2wpkh
                    Address    = "bc1q463gmsagg5u8wvqqcqj92yytt0pmevvg39h9jp",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
                    Signature  = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
                },
                new
                {
                    // p2wsh
                    Address    = "bc1qrr8fncdd8gsxajghfcy2upq37dvvc84t285g4lvfak9nrkqsalds9ms6qa",
                    PrivateKey = "5JEeah4w29axvf5Yg9v9PKv86zcCN9qVbizJDMHmiSUxBqDFoUT",
                    Message    = "this is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long messagethis is a very long message",
                    Signature  = "HFKBHewleUsotk6fWG0OvWS/E2pP4o5hixdD6ui60in/x4376FBI4DvtJYrljXLNJTG1pBOZG+qRT/7S9WiIBfQ="
                },
            };

            foreach (var test in tests)
            {
                var address = BitcoinAddress.Create(test.Address, Network.Main);
                var pkh     = (address as IPubkeyHashUsable);
                if (test.PrivateKey != null)
                {
                    var secret    = Network.Main.CreateBitcoinSecret(test.PrivateKey);
                    var signature = secret.PrivateKey.SignMessage(test.Message);
                    Assert.True(pkh.VerifyMessage(test.Message, signature));
                    Assert.True(secret.PubKey.VerifyMessage(test.Message, signature));
                }
                Assert.True(pkh.VerifyMessage(test.Message, test.Signature));
                Assert.True(!pkh.VerifyMessage("bad message", test.Signature));
            }
        }
コード例 #13
0
 public Program()
 {
     paymentSecret  = new BitcoinSecret("L5W89cAuSXoyzdY1yTyTTX8B3EHDbrVpWyk5T197eoyngvgczbAi");
     paymentAddress = paymentSecret.GetAddress();
 }
コード例 #14
0
        public async Task <IActionResult> LedgerConnection(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId,
            string command,
            // getinfo
            // getxpub
            int account = 0,
            // sendtoaddress
            string psbt       = null,
            string hintChange = null
            )
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(NotFound());
            }

            var network = NetworkProvider.GetNetwork <BTCPayNetwork>(walletId.CryptoCode);

            if (network == null)
            {
                throw new FormatException("Invalid value for crypto code");
            }
            var storeData          = (await Repository.FindStore(walletId.StoreId, GetUserId()));
            var derivationSettings = GetDerivationSchemeSettings(walletId, storeData);

            var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

            using (var normalOperationTimeout = new CancellationTokenSource())
                using (var signTimeout = new CancellationTokenSource())
                {
                    normalOperationTimeout.CancelAfter(TimeSpan.FromMinutes(30));
                    var    hw     = new LedgerHardwareWalletService(webSocket);
                    var    model  = new WalletSendLedgerModel();
                    object result = null;
                    try
                    {
                        if (command == "test")
                        {
                            result = await hw.Test(normalOperationTimeout.Token);
                        }
                        if (command == "sendtoaddress")
                        {
                            if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
                            {
                                throw new Exception($"{network.CryptoCode}: not started or fully synched");
                            }

                            var accountKey = derivationSettings.GetSigningAccountKeySettings();
                            // Some deployment does not have the AccountKeyPath set, let's fix this...
                            if (accountKey.AccountKeyPath == null)
                            {
                                // If the saved wallet key path is not present or incorrect, let's scan the wallet to see if it can sign strategy
                                var foundKeyPath = await hw.FindKeyPathFromDerivation(network,
                                                                                      derivationSettings.AccountDerivation,
                                                                                      normalOperationTimeout.Token);

                                accountKey.AccountKeyPath = foundKeyPath ?? throw new HardwareWalletException($"This store is not configured to use this ledger");
                                storeData.SetSupportedPaymentMethod(derivationSettings);
                                await Repository.UpdateStore(storeData);
                            }
                            // If it has already the AccountKeyPath, we did not looked up for it, so we need to check if we are on the right ledger
                            else
                            {
                                // Checking if ledger is right with the RootFingerprint is faster as it does not need to make a query to the parent xpub,
                                // but some deployment does not have it, so let's use AccountKeyPath instead
                                if (accountKey.RootFingerprint == null)
                                {
                                    var actualPubKey = await hw.GetExtPubKey(network, accountKey.AccountKeyPath, normalOperationTimeout.Token);

                                    if (!derivationSettings.AccountDerivation.GetExtPubKeys().Any(p => p.GetPublicKey() == actualPubKey.GetPublicKey()))
                                    {
                                        throw new HardwareWalletException($"This store is not configured to use this ledger");
                                    }
                                }
                                // We have the root fingerprint, we can check the root from it
                                else
                                {
                                    var actualPubKey = await hw.GetPubKey(network, new KeyPath(), normalOperationTimeout.Token);

                                    if (actualPubKey.GetHDFingerPrint() != accountKey.RootFingerprint.Value)
                                    {
                                        throw new HardwareWalletException($"This store is not configured to use this ledger");
                                    }
                                }
                            }

                            // Some deployment does not have the RootFingerprint set, let's fix this...
                            if (accountKey.RootFingerprint == null)
                            {
                                accountKey.RootFingerprint = (await hw.GetPubKey(network, new KeyPath(), normalOperationTimeout.Token)).GetHDFingerPrint();
                                storeData.SetSupportedPaymentMethod(derivationSettings);
                                await Repository.UpdateStore(storeData);
                            }

                            var psbtResponse = new CreatePSBTResponse()
                            {
                                PSBT          = PSBT.Parse(psbt, network.NBitcoinNetwork),
                                ChangeAddress = string.IsNullOrEmpty(hintChange) ? null : BitcoinAddress.Create(hintChange, network.NBitcoinNetwork)
                            };


                            derivationSettings.RebaseKeyPaths(psbtResponse.PSBT);

                            signTimeout.CancelAfter(TimeSpan.FromMinutes(5));
                            psbtResponse.PSBT = await hw.SignTransactionAsync(psbtResponse.PSBT, accountKey.GetRootedKeyPath(), accountKey.AccountKey, psbtResponse.ChangeAddress?.ScriptPubKey, signTimeout.Token);

                            result = new SendToAddressResult()
                            {
                                PSBT = psbtResponse.PSBT.ToBase64()
                            };
                        }
                    }
                    catch (OperationCanceledException)
                    { result = new LedgerTestResult()
                      {
                          Success = false, Error = "Timeout"
                      }; }
                    catch (Exception ex)
                    { result = new LedgerTestResult()
                      {
                          Success = false, Error = ex.Message
                      }; }
                    finally { hw.Dispose(); }
                    try
                    {
                        if (result != null)
                        {
                            UTF8Encoding UTF8NOBOM = new UTF8Encoding(false);
                            var          bytes     = UTF8NOBOM.GetBytes(JsonConvert.SerializeObject(result, _mvcJsonOptions.Value.SerializerSettings));
                            await webSocket.SendAsync(new ArraySegment <byte>(bytes), WebSocketMessageType.Text, true, new CancellationTokenSource(2000).Token);
                        }
                    }
                    catch { }
                    finally
                    {
                        await webSocket.CloseSocket();
                    }
                }
            return(new EmptyResult());
        }
コード例 #15
0
ファイル: base58_tests.cs プロジェクト: FluidChains/FullNode
        public void base58_keys_valid_parse()
        {
            TestCase[] tests = TestCase.read_json(TestDataLocations.GetFileFromDataFolder("base58_keys_valid.json"));
            Network    network;

            foreach (TestCase test in tests)
            {
                string strTest = test.ToString();
                if (test.Count < 3) // Allow for extra stuff (useful for comments)
                {
                    Assert.True(false, "Bad test " + strTest);
                    continue;
                }

                string exp_base58string = (string)test[0];
                byte[] exp_payload      = TestUtils.ParseHex((string)test[1]);
                //const Object &metadata = test[2].get_obj();
                bool isPrivkey = (bool)test.GetDynamic(2).isPrivkey;
                bool isTestnet = (bool)test.GetDynamic(2).isTestnet;
                if (isTestnet)
                {
                    network = KnownNetworks.TestNet;
                }
                else
                {
                    network = KnownNetworks.Main;
                }

                if (isPrivkey)
                {
                    bool isCompressed = (bool)test.GetDynamic(2).isCompressed;

                    // Must be valid private key
                    // Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
                    BitcoinSecret secret = network.CreateBitcoinSecret(exp_base58string);
                    //If not valid exception would throw

                    Key privkey = secret.PrivateKey;
                    Assert.True(privkey.IsCompressed == isCompressed, "compressed mismatch:" + strTest);
                    Assert.True(Utils.ArrayEqual(privkey.ToBytes(), exp_payload), "key mismatch:" + strTest);

                    // Private key must be invalid public key
                    Assert.Throws <FormatException>(() => network.CreateBitcoinAddress(exp_base58string));
                }
                else
                {
                    string exp_addrType = (string)test.GetDynamic(2).addrType; // "script" or "pubkey"
                                                                               // Must be valid public key
                    BitcoinAddress addr = network.CreateBitcoinAddress(exp_base58string);
                    Assert.True((addr is BitcoinScriptAddress) == (exp_addrType == "script"), "isScript mismatch" + strTest);

                    if (exp_addrType == "script")
                    {
                        Assert.True(addr.GetType() == typeof(BitcoinScriptAddress));
                    }
                    if (exp_addrType == "pubkey")
                    {
                        Assert.True(addr.GetType() == typeof(BitcoinPubKeyAddress));
                    }

                    Assert.Throws <FormatException>(() => network.CreateBitcoinSecret(exp_base58string));
                }
            }
        }
コード例 #16
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		/// <summary>
		/// Requires wallet support. Requires an unlocked wallet or an unencrypted wallet.
		/// </summary>
		/// <param name="address">A P2PKH or P2SH address to which the bitcoins should be sent</param>
		/// <param name="amount">The amount to spend</param>
		/// <param name="commentTx">A locally-stored (not broadcast) comment assigned to this transaction. Default is no comment</param>
		/// <param name="commentDest">A locally-stored (not broadcast) comment assigned to this transaction. Meant to be used for describing who the payment was sent to. Default is no comment</param>
		/// <returns>The TXID of the sent transaction</returns>
		public async Task<uint256> SendToAddressAsync(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null)
		{
			List<object> parameters = new List<object>();
			parameters.Add(address.ToString());
			parameters.Add(amount.ToString());
			if(commentTx != null)
				parameters.Add(commentTx);
			if(commentDest != null)
				parameters.Add(commentDest);
			var resp = await SendCommandAsync(RPCOperations.sendtoaddress, parameters.ToArray()).ConfigureAwait(false);
			return uint256.Parse(resp.Result.ToString());
		}
コード例 #17
0
        public Transaction SendWallMessage(string sourceTxId, string sourcePublicAddress,
                                           string stratPrivateKey, string destinationAddress, double amountTx, double feeTx, byte[] bytesMsg)
        {
            // RPC Connection to Stratis Blockchain
            var rpc = GetRPC();

            // Can either use the raw transaction hex from a wallet's getrawtransaction CLI command, or look up the equivalent information via RPC
            Transaction tx = rpc.GetRawTransaction(uint256.Parse(sourceTxId));

            // The destination address will receive 0.0001 STRAT
            BitcoinAddress destAddress = BitcoinAddress.Create(destinationAddress, Network.StratisMain);

            // Stratis Source Address - The source address is used to store the 'change' from the transaction - THIS IS THE SIGNATURE for the attestation
            BitcoinAddress sourceAddress = BitcoinAddress.Create(sourcePublicAddress, Network.StratisMain);

            // The private key must be the key for the source address to be able to send funds from the source address (String of ~52 ASCII)
            BitcoinSecret sourcePrivateKey = new BitcoinSecret(stratPrivateKey, Network.StratisMain);

            int       outputIndex = 0;
            int       indexTx     = 0;
            TxOutList listOutTx   = tx.Outputs;

            foreach (var item in listOutTx)
            {
                string opCode = item.ScriptPubKey.ToString();
                if (opCode.StartsWith("OP_DUP OP_HASH160"))
                {
                    string sAddress = new Script(opCode).GetDestinationAddress(Network.StratisMain).ToString();
                    if (sAddress.Equals(sourcePublicAddress))
                    {
                        outputIndex = indexTx;
                    }
                }
                ++indexTx;
            }

            // For the fee to be correctly calculated, the quantity of funds in the source transaction needs to be known
            Money remainingBalance = tx.Outputs[outputIndex].Value;

            // Now that the source Transaction is obtained, the right output needs to be selected as an input for the new transaction.
            OutPoint outPoint = new OutPoint(tx, outputIndex);

            // The source transaction's output (must be unspent) is the input for the new transaction
            Transaction sendTx = new Transaction();

            sendTx.Inputs.Add(new TxIn()
            {
                PrevOut = outPoint
            });

            // Can currently only send a maximum of 40 bytes in the null data transaction (bytesMsg)
            // Also note that a nulldata transaction currently has to have a nonzero value assigned to it.
            TxOut messageTxOut = new TxOut()
            {
                Value        = new Money((decimal)0.0001, MoneyUnit.BTC),
                ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytesMsg)
            };

            // For Attestation amountTx = 0.0001 STRAT is being sent to destAddress
            TxOut destTxOut = new TxOut()
            {
                Value        = new Money((decimal)amountTx, MoneyUnit.BTC),
                ScriptPubKey = destAddress.ScriptPubKey
            };
            double discBalance = feeTx + amountTx + 0.0001; // 0.0001 : nulldata transaction amount

            // This is what subsequent transactions use to prove ownership of the funds (more specifically, the private key used to create the ScriptPubKey is known)
            // Send the change back to the originating address.
            TxOut changeBackTxOut = new TxOut()
            {
                Value        = new Money(((remainingBalance.ToDecimal(MoneyUnit.BTC) - (decimal)discBalance)), MoneyUnit.BTC),
                ScriptPubKey = sourceAddress.ScriptPubKey
            };

            // changeBackTxOut = remainingBalance - 0.0001 (sent) - 0.0001 (network fee) - 0.0001 (nulldata)
            // Transactions without fees may violate consensus rules, or may not be relayed by other nodes on the network.

            // Add the outputs to the transaction being built
            sendTx.Outputs.Add(destTxOut);
            sendTx.Outputs.Add(messageTxOut);
            sendTx.Outputs.Add(changeBackTxOut);

            // Signing the transaction
            sendTx.Inputs[0].ScriptSig = sourceAddress.ScriptPubKey;

            // Sign the transaction using the specified private key
            sendTx.Sign(sourcePrivateKey, false);

            // Broadcast Transaction
            rpc.SendRawTransactionAsync(sendTx);

            return(sendTx);
        }
コード例 #18
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		public async Task ImportAddressAsync(BitcoinAddress address, string label, bool rescan)
		{
			await SendCommandAsync("importaddress", address.ToString(), label, rescan).ConfigureAwait(false);
		}
コード例 #19
0
        public async Task <IActionResult> LedgerConnection(
            [ModelBinder(typeof(WalletIdModelBinder))]
            WalletId walletId,
            string command,
            // getinfo
            // getxpub
            int account = 0,
            // sendtoaddress
            bool noChange      = false,
            string destination = null, string amount = null, string feeRate = null, string substractFees = null
            )
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(NotFound());
            }

            var cryptoCode       = walletId.CryptoCode;
            var storeData        = (await Repository.FindStore(walletId.StoreId, GetUserId()));
            var derivationScheme = GetPaymentMethod(walletId, storeData).DerivationStrategyBase;

            var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

            using (var normalOperationTimeout = new CancellationTokenSource())
                using (var signTimeout = new CancellationTokenSource())
                {
                    normalOperationTimeout.CancelAfter(TimeSpan.FromMinutes(30));
                    var    hw     = new HardwareWalletService(webSocket);
                    object result = null;
                    try
                    {
                        BTCPayNetwork network = null;
                        if (cryptoCode != null)
                        {
                            network = NetworkProvider.GetNetwork(cryptoCode);
                            if (network == null)
                            {
                                throw new FormatException("Invalid value for crypto code");
                            }
                        }

                        BitcoinAddress destinationAddress = null;
                        if (destination != null)
                        {
                            try
                            {
                                destinationAddress = BitcoinAddress.Create(destination.Trim(), network.NBitcoinNetwork);
                            }
                            catch { }
                            if (destinationAddress == null)
                            {
                                throw new FormatException("Invalid value for destination");
                            }
                        }

                        FeeRate feeRateValue = null;
                        if (feeRate != null)
                        {
                            try
                            {
                                feeRateValue = new FeeRate(Money.Satoshis(int.Parse(feeRate, CultureInfo.InvariantCulture)), 1);
                            }
                            catch { }
                            if (feeRateValue == null || feeRateValue.FeePerK <= Money.Zero)
                            {
                                throw new FormatException("Invalid value for fee rate");
                            }
                        }

                        Money amountBTC = null;
                        if (amount != null)
                        {
                            try
                            {
                                amountBTC = Money.Parse(amount);
                            }
                            catch { }
                            if (amountBTC == null || amountBTC <= Money.Zero)
                            {
                                throw new FormatException("Invalid value for amount");
                            }
                        }

                        bool subsctractFeesValue = false;
                        if (substractFees != null)
                        {
                            try
                            {
                                subsctractFeesValue = bool.Parse(substractFees);
                            }
                            catch { throw new FormatException("Invalid value for subtract fees"); }
                        }
                        if (command == "test")
                        {
                            result = await hw.Test(normalOperationTimeout.Token);
                        }
                        if (command == "sendtoaddress")
                        {
                            if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
                            {
                                throw new Exception($"{network.CryptoCode}: not started or fully synched");
                            }
                            var         strategy       = GetDirectDerivationStrategy(derivationScheme);
                            var         wallet         = _walletProvider.GetWallet(network);
                            var         change         = wallet.GetChangeAddressAsync(derivationScheme);
                            var         keypaths       = new Dictionary <Script, KeyPath>();
                            List <Coin> availableCoins = new List <Coin>();
                            foreach (var c in await wallet.GetUnspentCoins(derivationScheme))
                            {
                                keypaths.TryAdd(c.Coin.ScriptPubKey, c.KeyPath);
                                availableCoins.Add(c.Coin);
                            }

                            var changeAddress = await change;

                            var storeBlob    = storeData.GetStoreBlob();
                            var paymentId    = new Payments.PaymentMethodId(cryptoCode, Payments.PaymentTypes.BTCLike);
                            var foundKeyPath = storeBlob.GetWalletKeyPathRoot(paymentId);
                            // Some deployment have the wallet root key path saved in the store blob
                            // If it does, we only have to make 1 call to the hw to check if it can sign the given strategy,
                            if (foundKeyPath == null || !await hw.CanSign(network, strategy, foundKeyPath, normalOperationTimeout.Token))
                            {
                                // If the saved wallet key path is not present or incorrect, let's scan the wallet to see if it can sign strategy
                                foundKeyPath = await hw.FindKeyPath(network, strategy, normalOperationTimeout.Token);

                                if (foundKeyPath == null)
                                {
                                    throw new HardwareWalletException($"This store is not configured to use this ledger");
                                }
                                storeBlob.SetWalletKeyPathRoot(paymentId, foundKeyPath);
                                storeData.SetStoreBlob(storeBlob);
                                await Repository.UpdateStore(storeData);
                            }
retry:
                            var send = new[] { (
コード例 #20
0
ファイル: ColoredCoinsTests.cs プロジェクト: hu53yin/NBitcoin
		private static Transaction CreateSpecTransaction(NoSqlColoredTransactionRepository repo, Money dust, BitcoinAddress receiver, Transaction prior, Transaction issuanceA1, Transaction issuanceA2)
		{
			var testedTx = new Transaction();
			testedTx.Inputs.Add(new TxIn(new OutPoint(issuanceA1.GetHash(), 0)));
			testedTx.Inputs.Add(new TxIn(new OutPoint(issuanceA1.GetHash(), 1)));
			testedTx.Inputs.Add(new TxIn(new OutPoint(prior.GetHash(), 0)));
			testedTx.Inputs.Add(new TxIn(new OutPoint(issuanceA1.GetHash(), 2)));
			testedTx.Inputs.Add(new TxIn(new OutPoint(issuanceA1.GetHash(), 3)));
			testedTx.Inputs.Add(new TxIn(new OutPoint(issuanceA2.GetHash(), 0)));

			testedTx.Outputs.Add(new TxOut(Money.Parse("0.6"), receiver));
			testedTx.Outputs.Add(new TxOut(dust, receiver));
			testedTx.Outputs.Add(new TxOut(dust, new ColorMarker(new ulong[] { 0, 10, 6, 0, 7, 3 }).GetScript()));
			testedTx.Outputs.Add(new TxOut(dust, receiver));
			testedTx.Outputs.Add(new TxOut(dust, receiver));
			testedTx.Outputs.Add(new TxOut(dust, receiver));
			testedTx.Outputs.Add(new TxOut(dust, receiver));
			repo.Transactions.Put(testedTx.GetHash(), testedTx);
			return testedTx;
		}
コード例 #21
0
        public UnspentCoinModel[] ListUnspent(int minConfirmations = 1, int maxConfirmations = 9999999, string addressesJson = null)
        {
            List <BitcoinAddress> addresses = new List <BitcoinAddress>();

            if (!string.IsNullOrEmpty(addressesJson))
            {
                JsonConvert.DeserializeObject <List <string> >(addressesJson).ForEach(i => addresses.Add(BitcoinAddress.Create(i, this.FullNode.Network)));
            }

            WalletAccountReference accountReference = this.GetWalletAccountReference();
            IEnumerable <UnspentOutputReference> spendableTransactions = this.walletManager.GetSpendableTransactionsInAccount(accountReference, minConfirmations);

            var unspentCoins = new List <UnspentCoinModel>();

            foreach (var spendableTx in spendableTransactions)
            {
                if (spendableTx.Confirmations <= maxConfirmations)
                {
                    if (!addresses.Any() || addresses.Contains(BitcoinAddress.Create(spendableTx.Address.Address, this.FullNode.Network)))
                    {
                        unspentCoins.Add(new UnspentCoinModel()
                        {
                            Account         = accountReference.AccountName,
                            Address         = spendableTx.Address.Address,
                            Id              = spendableTx.Transaction.Id,
                            Index           = spendableTx.Transaction.Index,
                            Amount          = spendableTx.Transaction.Amount,
                            ScriptPubKeyHex = spendableTx.Transaction.ScriptPubKey.ToHex(),
                            RedeemScriptHex = null, // TODO: Currently don't support P2SH wallet addresses, review if we do.
                            Confirmations   = spendableTx.Confirmations,
                            IsSpendable     = !spendableTx.Transaction.IsSpent(),
                            IsSolvable      = !spendableTx.Transaction.IsSpent() // If it's spendable we assume it's solvable.
                        });
                    }
                }
            }

            return(unspentCoins.ToArray());
        }
コード例 #22
0
ファイル: Setup.cs プロジェクト: iob764rv/Blockchain-Coin
        static void Main(string[] args)
        {
          Network network = Network.TestNet;
          var treasurer = new BitcoinSecret("key")
          var alice = new BitcoinSecret("key");
          
          
          Console.WriteLine("treasurer key: " + treasurer.PrivateKey.GetWif(network));
          Console.WriteLine("Alice     key: " + alice.PrivateKey.GetWif(network));
          
          var scriptPubKey = PayToMultiSigTemplate
                .Instance
                .GenerateScriptPubKey(2, new[] { alice.PubKey, treasurer.PubKey });
          
          Console.WriteLine("PubKey script: " + scriptPubKey);
          
          var redeemScript = PayToMultiSigTemplate
            .Instance
            .GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, treasurer.PubKey });

          var paymentScript = redeemScript.PaymentScript;
          Console.WriteLine("paymentScript: " + paymentScript);
          
          
          Console.WriteLine("multi-sig address: " + redeemScript.Hash.GetAddress(network));
          var client = new QBitNinjaClient(network);

            // Update
          var receiveTransactionId = uint256.Parse("yourid");
          var receiveTransactionResponse = client.GetTransaction(receiveTransactionId).Result;
          Console.WriteLine(receiveTransactionResponse.TransactionId);
         
          var receiveTransactionResponse = client.GetTransaction(receiveTransactionId).Result;

          Console.WriteLine(receiveTransactionResponse.TransactionId);
          Console.WriteLine(receiveTransactionResponse.Block.Confirmations);
           
          var receivedCoins = receiveTransactionResponse.ReceivedCoins;
          OutPoint outpointToSpend = null;
          ScriptCoin coinToSpend = null;
           
          foreach (var c in receivedCoins)
          {
                    try
                {
                    coinToSpend = new ScriptCoin(c.Outpoint, c.TxOut, redeemScript);
                    outpointToSpend = c.Outpoint;
                    break;
                }
                catch { }
           if (outpointToSpend == null)
                throw new Exception("TxOut doesn't contain any our ScriptPubKey");
                Console.WriteLine("outpoint #{0}");
            
          var lucasAddress = BitcoinAddress.Create("address", network);

            TransactionBuilder builder = network.CreateTransactionBuilder();

            var minerFee = new Money(0.0005m, MoneyUnit.BTC);
            var txInAmount = (Money)receivedCoins[(int)outpointToSpend.N].Amount;
            var sendAmount = txInAmount - minerFee;
            
               Transaction unsigned =
                builder
                    .AddCoins(coinToSpend)
                    .Send(lucasAddress, sendAmount)
                    .SetChange(lucasAddress, ChangeType.Uncolored)
                    .BuildTransaction(sign: false);
            
                 Transaction aliceSigned =
                builder
                    .AddCoins(coinToSpend)
                    .AddKeys(alice)
                   
                   
               Transaction bobSigned =
                builder
                    .AddCoins(coinToSpend)
                    .AddKeys(bob)
                    .SignTransaction(aliceSigned);
コード例 #23
0
        public async Task <uint256> SendManyAsync(string fromAccount, string addressesJson, int minConf = 1, string comment = null, string subtractFeeFromJson = null, bool isReplaceable = false, int?confTarget = null, string estimateMode = "UNSET")
        {
            if (string.IsNullOrEmpty(addressesJson))
            {
                throw new RPCServerException(RPCErrorCode.RPC_INVALID_PARAMETER, "No valid output addresses specified.");
            }

            var addresses = new Dictionary <string, decimal>();

            try
            {
                // Outputs addresses are key-value pairs of address, amount. Translate to Receipient list.
                addresses = JsonConvert.DeserializeObject <Dictionary <string, decimal> >(addressesJson);
            }
            catch (JsonSerializationException ex)
            {
                throw new RPCServerException(RPCErrorCode.RPC_PARSE_ERROR, ex.Message);
            }

            if (addresses.Count == 0)
            {
                throw new RPCServerException(RPCErrorCode.RPC_INVALID_PARAMETER, "No valid output addresses specified.");
            }

            // Optional list of addresses to subtract fees from.
            IEnumerable <BitcoinAddress> subtractFeeFromAddresses = null;

            if (!string.IsNullOrEmpty(subtractFeeFromJson))
            {
                try
                {
                    subtractFeeFromAddresses = JsonConvert.DeserializeObject <List <string> >(subtractFeeFromJson).Select(i => BitcoinAddress.Create(i, this.FullNode.Network));
                }
                catch (JsonSerializationException ex)
                {
                    throw new RPCServerException(RPCErrorCode.RPC_PARSE_ERROR, ex.Message);
                }
            }

            var recipients = new List <Recipient>();

            foreach (var address in addresses)
            {
                // Check for duplicate recipients
                var recipientAddress = BitcoinAddress.Create(address.Key, this.FullNode.Network).ScriptPubKey;
                if (recipients.Any(r => r.ScriptPubKey == recipientAddress))
                {
                    throw new RPCServerException(RPCErrorCode.RPC_INVALID_PARAMETER, string.Format("Invalid parameter, duplicated address: {0}.", recipientAddress));
                }

                var recipient = new Recipient
                {
                    ScriptPubKey          = recipientAddress,
                    Amount                = Money.Coins(address.Value),
                    SubtractFeeFromAmount = subtractFeeFromAddresses == null ? false : subtractFeeFromAddresses.Contains(BitcoinAddress.Create(address.Key, this.FullNode.Network))
                };

                recipients.Add(recipient);
            }

            WalletAccountReference accountReference = this.GetWalletAccountReference();

            var context = new TransactionBuildContext(this.FullNode.Network)
            {
                AccountReference = accountReference,
                MinConfirmations = minConf,
                Shuffle          = true, // We shuffle transaction outputs by default as it's better for anonymity.
                Recipients       = recipients,
                CacheSecret      = false
            };

            // Set fee type for transaction build context.
            context.FeeType = FeeType.Medium;

            if (estimateMode.Equals("ECONOMICAL", StringComparison.InvariantCultureIgnoreCase))
            {
                context.FeeType = FeeType.Low;
            }
            else if (estimateMode.Equals("CONSERVATIVE", StringComparison.InvariantCultureIgnoreCase))
            {
                context.FeeType = FeeType.High;
            }

            try
            {
                // Log warnings for currently unsupported parameters.
                if (!string.IsNullOrEmpty(comment))
                {
                    this.logger.LogWarning("'comment' parameter is currently unsupported. Ignored.");
                }

                if (isReplaceable)
                {
                    this.logger.LogWarning("'replaceable' parameter is currently unsupported. Ignored.");
                }

                if (confTarget != null)
                {
                    this.logger.LogWarning("'conf_target' parameter is currently unsupported. Ignored.");
                }

                Transaction transaction = this.walletTransactionHandler.BuildTransaction(context);
                await this.broadcasterManager.BroadcastTransactionAsync(transaction);

                return(transaction.GetHash());
            }
            catch (SecurityException)
            {
                throw new RPCServerException(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED, "Wallet unlock needed");
            }
            catch (WalletException exception)
            {
                throw new RPCServerException(RPCErrorCode.RPC_WALLET_ERROR, exception.Message);
            }
            catch (NotImplementedException exception)
            {
                throw new RPCServerException(RPCErrorCode.RPC_MISC_ERROR, exception.Message);
            }
        }
コード例 #24
0
        private List <TransactionInformation> Filter(RPCWalletEntry[] entries, bool includeUnconf, BitcoinAddress address)
        {
            List <TransactionInformation> results    = new List <TransactionInformation>();
            HashSet <uint256>             resultsSet = new HashSet <uint256>();

            foreach (var obj in entries)
            {
                //May have duplicates
                if (!resultsSet.Contains(obj.TransactionId))
                {
                    var confirmations = obj.Confirmations;
                    var tx            = _Cache.GetTransaction(obj.TransactionId);

                    if (tx == null || (!includeUnconf && confirmations == 0))
                    {
                        continue;
                    }

                    if (tx.Outputs.Any(o => o.ScriptPubKey == address.ScriptPubKey) ||
                        tx.Inputs.Any(o => o.ScriptSig.GetSigner().ScriptPubKey == address.ScriptPubKey))
                    {
                        resultsSet.Add(obj.TransactionId);
                        results.Add(new TransactionInformation()
                        {
                            Transaction   = tx,
                            Confirmations = confirmations
                        });
                    }
                }
            }
            return(results);
        }
コード例 #25
0
 public uint256 SendToAddress(BitcoinAddress address, Money amount)
 {
     return(SendToAddressAsync(address, amount).GetAwaiter().GetResult());
 }
コード例 #26
0
        /// <summary>
        /// Creates a cold staking withdrawal <see cref="Transaction"/>.
        /// </summary>
        /// <remarks>
        /// Cold staking withdrawal is performed on the wallet that is in the role of the cold staking cold wallet.
        /// </remarks>
        /// <param name="walletTransactionHandler">The wallet transaction handler used to build the transaction.</param>
        /// <param name="receivingAddress">The address that will receive the withdrawal.</param>
        /// <param name="walletName">The name of the wallet in the role of cold wallet.</param>
        /// <param name="walletPassword">The wallet password.</param>
        /// <param name="amount">The amount to remove from cold staking.</param>
        /// <param name="feeAmount">The fee to pay for cold staking transaction withdrawal.</param>
        /// <returns>The <see cref="Transaction"/> for cold staking withdrawal.</returns>
        /// <exception cref="WalletException">Thrown if the receiving address is in a cold staking account in this wallet.</exception>
        /// <exception cref="ArgumentNullException">Thrown if the receiving address is invalid.</exception>
        internal Transaction GetColdStakingWithdrawalTransaction(IWalletTransactionHandler walletTransactionHandler, string receivingAddress,
                                                                 string walletName, string walletPassword, Money amount, Money feeAmount)
        {
            Guard.NotEmpty(receivingAddress, nameof(receivingAddress));
            Guard.NotEmpty(walletName, nameof(walletName));
            Guard.NotNull(amount, nameof(amount));
            Guard.NotNull(feeAmount, nameof(feeAmount));

            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:'{5}',{6}:'{7}'",
                                 nameof(receivingAddress), receivingAddress,
                                 nameof(walletName), walletName,
                                 nameof(amount), amount,
                                 nameof(feeAmount), feeAmount
                                 );

            Wallet.Wallet wallet = this.GetWalletByName(walletName);

            // Get the cold staking account.
            HdAccount coldAccount = this.GetColdStakingAccount(wallet, true);

            if (coldAccount == null)
            {
                this.logger.LogTrace("(-)[COLDSTAKE_ACCOUNT_DOES_NOT_EXIST]");
                throw new WalletException("The cold wallet account does not exist.");
            }

            // Prevent reusing cold stake addresses as regular withdrawal addresses.
            if (coldAccount.ExternalAddresses.Concat(coldAccount.InternalAddresses).Select(a => a.Address.ToString()).Contains(receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_COLD_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking cold wallet account.");
            }

            HdAccount hotAccount = this.GetColdStakingAccount(wallet, false);

            if (hotAccount != null && hotAccount.ExternalAddresses.Concat(hotAccount.InternalAddresses).Select(a => a.Address.ToString()).Contains(receivingAddress))
            {
                this.logger.LogTrace("(-)[COLDSTAKE_INVALID_HOT_WALLET_ADDRESS_USAGE]");
                throw new WalletException("You can't send the money to a cold staking hot wallet account.");
            }

            // Send the money to the receiving address.
            Script destination = BitcoinAddress.Create(receivingAddress, wallet.Network).ScriptPubKey;

            // Create the transaction build context (used in BuildTransaction).
            var accountReference = new WalletAccountReference(walletName, coldAccount.Name);
            var context          = new TransactionBuildContext(wallet.Network)
            {
                AccountReference = accountReference,
                // Specify a dummy change address to prevent a change (internal) address from being created.
                // Will be changed after the transacton is built and before it is signed.
                ChangeAddress    = coldAccount.ExternalAddresses.First(),
                TransactionFee   = feeAmount,
                MinConfirmations = 0,
                Shuffle          = false,
                Sign             = false,
                Recipients       = new[] { new Recipient {
                                               Amount = amount, ScriptPubKey = destination
                                           } }.ToList()
            };

            // Register the cold staking builder extension with the transaction builder.
            context.TransactionBuilder.Extensions.Add(new ColdStakingBuilderExtension(false));

            // Avoid script errors due to missing scriptSig.
            context.TransactionBuilder.StandardTransactionPolicy.ScriptVerify = null;

            // Build the transaction according to the settings recorded in the context.
            Transaction transaction = walletTransactionHandler.BuildTransaction(context);

            // Map OutPoint to UnspentOutputReference.
            Dictionary <OutPoint, UnspentOutputReference> mapOutPointToUnspentOutput = this.GetSpendableTransactionsInAccount(accountReference)
                                                                                       .ToDictionary(unspent => unspent.ToOutPoint(), unspent => unspent);

            // Set the cold staking scriptPubKey on the change output.
            TxOut changeOutput = transaction.Outputs.SingleOrDefault(output => (output.ScriptPubKey != destination) && (output.Value != 0));

            if (changeOutput != null)
            {
                // Find the largest input.
                TxIn largestInput = transaction.Inputs.OrderByDescending(input => mapOutPointToUnspentOutput[input.PrevOut].Transaction.Amount).Take(1).Single();

                // Set the scriptPubKey of the change output to the scriptPubKey of the largest input.
                changeOutput.ScriptPubKey = mapOutPointToUnspentOutput[largestInput.PrevOut].Transaction.ScriptPubKey;
            }

            // Add keys for signing inputs.
            foreach (TxIn input in transaction.Inputs)
            {
                UnspentOutputReference unspent = mapOutPointToUnspentOutput[input.PrevOut];
                context.TransactionBuilder.AddKeys(wallet.GetExtendedPrivateKeyForAddress(walletPassword, unspent.Address));
            }

            // Sign the transaction.
            context.TransactionBuilder.SignTransactionInPlace(transaction);

            this.logger.LogTrace("(-):'{0}'", transaction.GetHash());
            return(transaction);
        }
コード例 #27
0
        public async Task CanPlayWithPSBT()
        {
            using var tester = CreateServerTester();
            await tester.StartAsync();

            var user = tester.NewAccount();

            user.GrantAccess();
            user.RegisterDerivationScheme("BTC");
            var invoice = user.BitPay.CreateInvoice(new Invoice()
            {
                Price             = 10,
                Currency          = "USD",
                PosData           = "posData",
                OrderId           = "orderId",
                ItemDesc          = "Some \", description",
                FullNotifications = true
            }, Facade.Merchant);
            var cashCow        = tester.ExplorerNode;
            var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network);

            cashCow.SendToAddress(invoiceAddress, Money.Coins(1.5m));
            TestUtils.Eventually(() =>
            {
                invoice = user.BitPay.GetInvoice(invoice.Id);
                Assert.Equal("paid", invoice.Status);
            });

            var walletController = user.GetController <UIWalletsController>();
            var walletId         = new WalletId(user.StoreId, "BTC");
            var sendDestination  = new Key().PubKey.Hash.GetAddress(user.SupportedNetwork.NBitcoinNetwork).ToString();
            var sendModel        = new WalletSendModel()
            {
                Outputs = new List <WalletSendModel.TransactionOutput>()
                {
                    new WalletSendModel.TransactionOutput()
                    {
                        DestinationAddress = sendDestination,
                        Amount             = 0.1m,
                    }
                },
                FeeSatoshiPerByte = 1,
                CurrentBalance    = 1.5m
            };

            string redirectedPSBT = AssertRedirectedPSBT(await walletController.WalletSend(walletId, sendModel, command: "analyze-psbt"), nameof(walletController.WalletPSBT));
            var    vmPSBT         = await walletController.WalletPSBT(walletId, new WalletPSBTViewModel()
            {
                PSBT = redirectedPSBT
            }).AssertViewModelAsync <WalletPSBTViewModel>();

            var unsignedPSBT = PSBT.Parse(vmPSBT.PSBT, user.SupportedNetwork.NBitcoinNetwork);

            Assert.NotNull(vmPSBT.Decoded);

            var filePSBT = (FileContentResult)(await walletController.WalletPSBT(walletId, vmPSBT, "save-psbt"));

            PSBT.Load(filePSBT.FileContents, user.SupportedNetwork.NBitcoinNetwork);

            var vmPSBT2 = await walletController.WalletPSBT(walletId, new WalletPSBTViewModel
            {
                SigningContext = new SigningContextModel
                {
                    PSBT = AssertRedirectedPSBT(await walletController.WalletPSBT(walletId, vmPSBT, "broadcast"), nameof(walletController.WalletPSBTReady))
                }
            }).AssertViewModelAsync <WalletPSBTViewModel>();

            Assert.NotEmpty(vmPSBT2.Inputs.Where(i => i.Error != null));
            Assert.Equal(vmPSBT.PSBT, vmPSBT2.SigningContext.PSBT);

            var signedPSBT = unsignedPSBT.Clone();

            signedPSBT.SignAll(user.DerivationScheme, user.GenerateWalletResponseV.AccountHDKey, user.GenerateWalletResponseV.AccountKeyPath);
            vmPSBT.PSBT = signedPSBT.ToBase64();
            var psbtReady = await walletController.WalletPSBT(walletId, new WalletPSBTViewModel
            {
                SigningContext = new SigningContextModel
                {
                    PSBT = AssertRedirectedPSBT(await walletController.WalletPSBT(walletId, vmPSBT, "broadcast"), nameof(walletController.WalletPSBTReady))
                }
            }).AssertViewModelAsync <WalletPSBTViewModel>();

            Assert.Equal(2 + 1, psbtReady.Destinations.Count); // The fee is a destination
            Assert.Contains(psbtReady.Destinations, d => d.Destination == sendDestination && !d.Positive);
            Assert.Contains(psbtReady.Destinations, d => d.Positive);

            vmPSBT.PSBT = unsignedPSBT.ToBase64();
            var combineVM = await walletController.WalletPSBT(walletId, vmPSBT, "combine").AssertViewModelAsync <WalletPSBTCombineViewModel>();

            Assert.Equal(vmPSBT.PSBT, combineVM.OtherPSBT);
            combineVM.PSBT = signedPSBT.ToBase64();
            var psbt = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM), nameof(walletController.WalletPSBT));

            var signedPSBT2 = PSBT.Parse(psbt, user.SupportedNetwork.NBitcoinNetwork);

            Assert.True(signedPSBT.TryFinalize(out _));
            Assert.True(signedPSBT2.TryFinalize(out _));
            Assert.Equal(signedPSBT, signedPSBT2);

            // Can use uploaded file?
            combineVM.PSBT             = null;
            combineVM.UploadedPSBTFile = TestUtils.GetFormFile("signedPSBT", signedPSBT.ToBytes());
            psbt        = AssertRedirectedPSBT(await walletController.WalletPSBTCombine(walletId, combineVM), nameof(walletController.WalletPSBT));
            signedPSBT2 = PSBT.Parse(psbt, user.SupportedNetwork.NBitcoinNetwork);
            Assert.True(signedPSBT.TryFinalize(out _));
            Assert.True(signedPSBT2.TryFinalize(out _));
            Assert.Equal(signedPSBT, signedPSBT2);

            var ready = (await walletController.WalletPSBT(walletId, new WalletPSBTViewModel
            {
                SigningContext = new SigningContextModel(signedPSBT)
            })).AssertViewModel <WalletPSBTViewModel>();

            Assert.Equal(signedPSBT.ToBase64(), ready.SigningContext.PSBT);
            psbt = AssertRedirectedPSBT(await walletController.WalletPSBTReady(walletId, ready, command: "analyze-psbt"), nameof(walletController.WalletPSBT));
            Assert.Equal(signedPSBT.ToBase64(), psbt);
            var redirect = Assert.IsType <RedirectToActionResult>(await walletController.WalletPSBTReady(walletId, ready, command: "broadcast"));

            Assert.Equal(nameof(walletController.WalletTransactions), redirect.ActionName);

            //test base64 psbt file
            Assert.False(string.IsNullOrEmpty(Assert.IsType <WalletPSBTViewModel>(
                                                  Assert.IsType <ViewResult>(
                                                      await walletController.WalletPSBT(walletId,
                                                                                        new WalletPSBTViewModel
            {
                UploadedPSBTFile = TestUtils.GetFormFile("base64", signedPSBT.ToBase64())
            })).Model).PSBT));
        }
コード例 #28
0
        public async Task PaymentControllerTests()
        {
            using (var tester = ServerTester.Create())
            {
                await tester.StartAsync();

                var user = tester.NewAccount();
                user.GrantAccess();
                await user.MakeAdmin();

                var client = await user.CreateClient(Policies.Unrestricted);

                var viewOnly = await user.CreateClient(Policies.CanViewPaymentRequests);

                //create payment request

                //validation errors
                await AssertValidationError(new[] { "Amount", "Currency" }, async() =>
                {
                    await client.CreatePaymentRequest(user.StoreId, new CreatePaymentRequestRequest()
                    {
                        Title = "A"
                    });
                });
                await AssertValidationError(new[] { "Amount" }, async() =>
                {
                    await client.CreatePaymentRequest(user.StoreId,
                                                      new CreatePaymentRequestRequest()
                    {
                        Title = "A", Currency = "BTC", Amount = 0
                    });
                });
                await AssertValidationError(new[] { "Currency" }, async() =>
                {
                    await client.CreatePaymentRequest(user.StoreId,
                                                      new CreatePaymentRequestRequest()
                    {
                        Title = "A", Currency = "helloinvalid", Amount = 1
                    });
                });
                await AssertHttpError(403, async() =>
                {
                    await viewOnly.CreatePaymentRequest(user.StoreId,
                                                        new CreatePaymentRequestRequest()
                    {
                        Title = "A", Currency = "helloinvalid", Amount = 1
                    });
                });

                var newPaymentRequest = await client.CreatePaymentRequest(user.StoreId,
                                                                          new CreatePaymentRequestRequest()
                {
                    Title = "A", Currency = "USD", Amount = 1
                });

                //list payment request
                var paymentRequests = await viewOnly.GetPaymentRequests(user.StoreId);

                Assert.NotNull(paymentRequests);
                Assert.Single(paymentRequests);
                Assert.Equal(newPaymentRequest.Id, paymentRequests.First().Id);

                //get payment request
                var paymentRequest = await viewOnly.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);

                Assert.Equal(newPaymentRequest.Title, paymentRequest.Title);

                //update payment request
                var updateRequest = JObject.FromObject(paymentRequest).ToObject <UpdatePaymentRequestRequest>();
                updateRequest.Title = "B";
                await AssertHttpError(403, async() =>
                {
                    await viewOnly.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);
                });

                await client.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);

                paymentRequest = await client.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);

                Assert.Equal(updateRequest.Title, paymentRequest.Title);

                //archive payment request
                await AssertHttpError(403, async() =>
                {
                    await viewOnly.ArchivePaymentRequest(user.StoreId, paymentRequest.Id);
                });

                await client.ArchivePaymentRequest(user.StoreId, paymentRequest.Id);

                Assert.DoesNotContain(paymentRequest.Id,
                                      (await client.GetPaymentRequests(user.StoreId)).Select(data => data.Id));

                //let's test some payment stuff
                await user.RegisterDerivationSchemeAsync("BTC");

                var paymentTestPaymentRequest = await client.CreatePaymentRequest(user.StoreId,
                                                                                  new CreatePaymentRequestRequest()
                {
                    Amount = 0.1m, Currency = "BTC", Title = "Payment test title"
                });

                var invoiceId = Assert.IsType <string>(Assert.IsType <OkObjectResult>(await user.GetController <PaymentRequestController>()
                                                                                      .PayPaymentRequest(paymentTestPaymentRequest.Id, false)).Value);
                var invoice = user.BitPay.GetInvoice(invoiceId);
                await tester.WaitForEvent <InvoiceDataChangedEvent>(async() =>
                {
                    await tester.ExplorerNode.SendToAddressAsync(
                        BitcoinAddress.Create(invoice.BitcoinAddress, tester.ExplorerNode.Network), invoice.BtcDue);
                });

                await TestUtils.EventuallyAsync(async() =>
                {
                    Assert.Equal(Invoice.STATUS_PAID, user.BitPay.GetInvoice(invoiceId).Status);
                    Assert.Equal(PaymentRequestData.PaymentRequestStatus.Completed, (await client.GetPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id)).Status);
                });
            }
        }
コード例 #29
0
ファイル: RPCClient.cs プロジェクト: pkahle/NBitcoin
        public BitcoinSecret DumpPrivKey(BitcoinAddress address)
        {
            var response = SendCommand("dumpprivkey", address.ToString());

            return(Network.CreateFromBase58Data <BitcoinSecret>((string)response.Result));
        }
コード例 #30
0
        public Transaction FundRawTx(RPCClient rpc, Transaction rawTx, Money feeAmount, BitcoinAddress changeAddress)
        {
            // The transaction funding logic will ensure that a transaction fee of
            // feeAmount is included. The remaining difference between the value of
            // the inputs and the outputs will be returned as a change address
            // output

            var unspentOutputs = rpc.ListUnspent();
            var totalFunded    = new Money(0);

            foreach (var unspent in unspentOutputs)
            {
                if (!unspent.IsSpendable)
                {
                    continue;
                }

                if (totalFunded < (rawTx.TotalOut + feeAmount))
                {
                    rawTx.Inputs.Add(new TxIn()
                    {
                        PrevOut = unspent.OutPoint
                    });

                    // By this point the input array will have at least one element
                    // starting at index 0
                    rawTx.Inputs[rawTx.Inputs.Count - 1].ScriptSig = unspent.ScriptPubKey;

                    // Need to accurately account for how much funding is assigned
                    // to the inputs so that change can be correctly calculated later
                    totalFunded += unspent.Amount;
                }
                else
                {
                    break;
                }
            }

            if (totalFunded < (rawTx.TotalOut + feeAmount))
            {
                throw new Exception("Insufficient unspent funds for registration");
            }

            var change = totalFunded - rawTx.TotalOut - feeAmount;

            if (change < 0)
            {
                throw new Exception("Change amount cannot be negative for registration transaction");
            }

            rawTx.Outputs.Add(new TxOut()
            {
                Value        = change,
                ScriptPubKey = changeAddress.ScriptPubKey
            });

            return(rawTx);
        }
コード例 #31
0
 internal AddressHistoryRecord(BitcoinAddress address, BalanceOperation operation)
 {
     Address   = address;
     Operation = operation;
 }
コード例 #32
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		/// <summary>
		/// Requires wallet support. Requires an unlocked wallet or an unencrypted wallet.
		/// </summary>
		/// <param name="address">A P2PKH or P2SH address to which the bitcoins should be sent</param>
		/// <param name="amount">The amount to spend</param>
		/// <param name="commentTx">A locally-stored (not broadcast) comment assigned to this transaction. Default is no comment</param>
		/// <param name="commentDest">A locally-stored (not broadcast) comment assigned to this transaction. Meant to be used for describing who the payment was sent to. Default is no comment</param>
		/// <returns>The TXID of the sent transaction</returns>
		public uint256 SendToAddress(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null)
		{
			uint256 txid = null;
			try
			{
				txid = SendToAddressAsync(address, amount, commentTx, commentDest).Result;
			}
			catch(AggregateException aex)
			{
				ExceptionDispatchInfo.Capture(aex.InnerException).Throw();
			}
			return txid;
		}
        public void DepositCheckNewTransactionsTest_TestIfDepositHandlingIsDoneAsExpected_VerifiesThroughReturnedValue()
        {
            // Submits withdraw to own address, after the first NewTransactionInterval has been elapsed.
            // Checks if new deposit has been created by the DepositAPplicationService and DepositAddress marked used
            if (_shouldRunTests)
            {
                ICoinClientService coinClientService =
                    (ICoinClientService)ContextRegistry.GetContext()["DogecoinClientService"];
                IFundsPersistenceRepository fundsPersistenceRepository =
                    (IFundsPersistenceRepository)ContextRegistry.GetContext()["FundsPersistenceRepository"];
                IDepositAddressRepository depositAddressRepository =
                    (IDepositAddressRepository)ContextRegistry.GetContext()["DepositAddressRepository"];
                IDepositRepository depositRepository =
                    (IDepositRepository)ContextRegistry.GetContext()["DepositRepository"];

                Currency       currency       = new Currency("DOGE", true);
                AccountId      accountId      = new AccountId(1);
                string         newAddress     = coinClientService.CreateNewAddress();
                BitcoinAddress bitcoinAddress = new BitcoinAddress(newAddress);
                DepositAddress depositAddress = new DepositAddress(currency, bitcoinAddress,
                                                                   AddressStatus.New, DateTime.Now, accountId);
                fundsPersistenceRepository.SaveOrUpdate(depositAddress);

                // Check that there is no deposit with this address present
                List <Deposit> deposits = depositRepository.GetDepositsByBitcoinAddress(bitcoinAddress);
                Assert.AreEqual(0, deposits.Count);

                ManualResetEvent manualResetEvent = new ManualResetEvent(false);

                // Wait for the first interval to elapse, and then withdraw, because only then we will be able to figure if a
                // new transaction has been received
                manualResetEvent.WaitOne(Convert.ToInt32(coinClientService.PollingInterval + 3000));

                manualResetEvent.Reset();
                bool eventFired = false;
                coinClientService.DepositArrived += delegate(string curr, List <Tuple <string, string, decimal, string> > pendingList)
                {
                    eventFired = true;
                    manualResetEvent.Set();
                };

                Withdraw withdraw = new Withdraw(currency, Guid.NewGuid().ToString(), DateTime.Now, WithdrawType.Bitcoin,
                                                 Amount, 0.001m, TransactionStatus.Pending, accountId,
                                                 new BitcoinAddress(newAddress));
                string commitWithdraw = coinClientService.CommitWithdraw(withdraw.BitcoinAddress.Value, withdraw.Amount);
                Assert.IsNotNull(commitWithdraw);
                Assert.IsFalse(string.IsNullOrEmpty(commitWithdraw));
                manualResetEvent.WaitOne();

                Assert.IsTrue(eventFired);
                depositAddress = depositAddressRepository.GetDepositAddressByAddress(bitcoinAddress);
                Assert.IsNotNull(depositAddress);
                Assert.AreEqual(AddressStatus.Used, depositAddress.Status);

                // See If DepositApplicationService created the deposit instance
                deposits = depositRepository.GetDepositsByBitcoinAddress(bitcoinAddress);
                Deposit deposit = deposits.Single();
                Assert.IsNotNull(deposit);
                Assert.AreEqual(Amount, deposit.Amount);
                Assert.AreEqual(currency.Name, deposit.Currency.Name);
                Assert.IsFalse(string.IsNullOrEmpty(deposit.TransactionId.Value));
                Assert.AreEqual(bitcoinAddress.Value, deposit.BitcoinAddress.Value);
                Assert.AreEqual(DepositType.Default, deposit.Type);
                Assert.AreEqual(0, deposit.Confirmations);
                Assert.AreEqual(accountId.Value, deposit.AccountId.Value);
                Assert.AreEqual(TransactionStatus.Pending, deposit.Status);
            }
        }
コード例 #34
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		public void ImportAddress(BitcoinAddress address)
		{
			SendCommand("importaddress", address.ToString());
		}
コード例 #35
0
        public async Task <BitcoinAddress> NewAddressAsync()
        {
            var obj = await SendCommandAsync <JObject>("newaddr");

            return(BitcoinAddress.Create(obj.Property("address").Value.Value <string>(), Network));
        }
コード例 #36
0
ファイル: RPCClient.cs プロジェクト: crowar/NBitcoin
		public async Task ImportAddressAsync(BitcoinAddress address)
		{
			await SendCommandAsync("importaddress", address.ToString()).ConfigureAwait(false);
		}
コード例 #37
0
ファイル: Extensions.cs プロジェクト: junderw/NBXplorer
 public static void WaitForTransaction(this LongPollingNotificationSession session, BitcoinAddress address, uint256 txId)
 {
     session.WaitForTransaction(TrackedSource.Create(address), txId);
 }
コード例 #38
0
ファイル: RPCClient.cs プロジェクト: hu53yin/NBitcoin
		public BitcoinSecret DumpPrivKey(BitcoinAddress address)
		{
			var response = SendCommand("dumpprivkey", address.ToString());
			return Network.CreateFromBase58Data<BitcoinSecret>((string)response.Result);
		}
コード例 #39
0
        private static TrackedSource GetTrackedSource(DerivationStrategyBase derivationScheme, BitcoinAddress address)
        {
            TrackedSource trackedSource = null;

            if (address != null)
            {
                trackedSource = new AddressTrackedSource(address);
            }
            if (derivationScheme != null)
            {
                trackedSource = new DerivationSchemeTrackedSource(derivationScheme);
            }
            return(trackedSource);
        }
コード例 #40
0
ファイル: ColoredCoinsTests.cs プロジェクト: hu53yin/NBitcoin
		public void CanParseColoredAddress()
		{
			var address = new BitcoinAddress("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM");
			var colored = address.ToColoredAddress();
			Assert.Equal("akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy", colored.ToWif());
			Assert.Equal(address.ScriptPubKey, colored.ScriptPubKey);

			var testAddress = address.ToNetwork(Network.TestNet);
			var testColored = testAddress.ToColoredAddress();

			Assert.Equal(Network.TestNet, testAddress.Network);
			Assert.Equal(address.Hash, testAddress.Hash);

			Assert.Equal(colored.ToNetwork(Network.TestNet), testColored);

			Assert.Equal(testAddress.ScriptPubKey, testColored.ScriptPubKey);

			Assert.Equal(Network.TestNet, testColored.Network);
			testColored = new BitcoinColoredAddress("bWqaKUZETiECYgmJNbNZUoanBxnAzoVjCNx");
			Assert.Equal(Network.TestNet, testColored.Network);
			Assert.Equal(colored.ToNetwork(Network.TestNet), testColored);
		}
コード例 #41
0
        public async Task <IActionResult> GetTransactions(
            string cryptoCode,
            [ModelBinder(BinderType = typeof(DerivationStrategyModelBinder))]
            DerivationStrategyBase derivationScheme,
            [ModelBinder(BinderType = typeof(BitcoinAddressModelBinder))]
            BitcoinAddress address,
            [ModelBinder(BinderType = typeof(UInt256ModelBinding))]
            uint256 txId            = null,
            bool includeTransaction = true)
        {
            var trackedSource = GetTrackedSource(derivationScheme, address);

            if (trackedSource == null)
            {
                throw new ArgumentNullException(nameof(trackedSource));
            }
            TransactionInformation fetchedTransactionInfo = null;

            var network = GetNetwork(cryptoCode, false);
            var chain   = ChainProvider.GetChain(network);
            var repo    = RepositoryProvider.GetRepository(network);

            var response      = new GetTransactionsResponse();
            int currentHeight = chain.Height;

            response.Height = currentHeight;
            var txs = await GetAnnotatedTransactions(repo, chain, trackedSource, txId);

            foreach (var item in new[]
            {
                new
                {
                    TxSet = response.ConfirmedTransactions,
                    AnnotatedTx = txs.ConfirmedTransactions
                },
                new
                {
                    TxSet = response.UnconfirmedTransactions,
                    AnnotatedTx = txs.UnconfirmedTransactions
                },
                new
                {
                    TxSet = response.ReplacedTransactions,
                    AnnotatedTx = txs.ReplacedTransactions
                },
            })
            {
                foreach (var tx in item.AnnotatedTx)
                {
                    var txInfo = new TransactionInformation()
                    {
                        BlockHash     = tx.Height.HasValue ? tx.Record.BlockHash : null,
                        Height        = tx.Height,
                        TransactionId = tx.Record.TransactionHash,
                        Transaction   = includeTransaction ? tx.Record.Transaction : null,
                        Confirmations = tx.Height.HasValue ? currentHeight - tx.Height.Value + 1 : 0,
                        Timestamp     = tx.Record.FirstSeen,
                        Inputs        = tx.Record.SpentOutpoints.Select(o => txs.GetUTXO(o)).Where(o => o != null).ToList(),
                        Outputs       = tx.Record.GetReceivedOutputs().ToList()
                    };

                    if (txId == null || txId == txInfo.TransactionId)
                    {
                        item.TxSet.Transactions.Add(txInfo);
                    }
                    if (txId != null && txId == txInfo.TransactionId)
                    {
                        fetchedTransactionInfo = txInfo;
                    }

                    txInfo.BalanceChange = txInfo.Outputs.Select(o => o.Value).Sum() - txInfo.Inputs.Select(o => o.Value).Sum();
                }
                item.TxSet.Transactions.Reverse();                 // So the youngest transaction is generally first
            }



            if (txId == null)
            {
                return(Json(response));
            }
            else if (fetchedTransactionInfo == null)
            {
                return(NotFound());
            }
            else
            {
                return(Json(fetchedTransactionInfo));
            }
        }
コード例 #42
0
ファイル: transaction_tests.cs プロジェクト: knocte/NBitcoin
		private Coin RandomCoin(Money amount, BitcoinAddress receiver)
		{
			var outpoint = RandOutpoint();
			return new Coin(outpoint, new TxOut(amount, receiver));
		}
コード例 #43
0
ファイル: util_tests.cs プロジェクト: woutersmit/NBitcoin
		public void CanGenerateScriptFromAddress()
		{
			var address = new BitcoinAddress(new KeyId("47376c6f537d62177a2c41c4ca9b45829ab99083"), Network.Main);
			Assert.Equal("OP_DUP OP_HASH160 47376c6f537d62177a2c41c4ca9b45829ab99083 OP_EQUALVERIFY OP_CHECKSIG", address.ScriptPubKey.ToString());

			var scriptAddress = new BitcoinScriptAddress(new ScriptId("8f55563b9a19f321c211e9b9f38cdf686ea07845"), Network.Main);
			Assert.Equal("OP_HASH160 8f55563b9a19f321c211e9b9f38cdf686ea07845 OP_EQUAL", scriptAddress.ScriptPubKey.ToString());

			var pubKey = new PubKey("0359d3092e4a8d5f3b3948235b5dec7395259273ccf3c4e9d5e16695a3fc9588d6");
			Assert.Equal("OP_DUP OP_HASH160 4d29186f76581c7375d70499afd1d585149d42cd OP_EQUALVERIFY OP_CHECKSIG", pubKey.Hash.ScriptPubKey.ToString());
			Assert.Equal("0359d3092e4a8d5f3b3948235b5dec7395259273ccf3c4e9d5e16695a3fc9588d6 OP_CHECKSIG", pubKey.ScriptPubKey.ToString());

			Script script = new Script("0359d3092e4a8d5f3b3948235b5dec7395259273ccf3c4e9d5e16695a3fc9588d6 OP_CHECKSIG");
			Assert.Equal("OP_HASH160 a216e3bce8c1b3adf376731b6cd0b6936c4e053f OP_EQUAL", script.PaymentScript.ToString());
		}