예제 #1
0
        public async Task SendTestAsync()
        {
            Network      network  = Network.TestNet;
            SafeAccount  account  = new SafeAccount(1);
            string       path     = Path.Combine(Helpers.CommittedWalletsFolderPath, $"Sending{network}.json");
            const string password = "";
            Safe         safe     = await Safe.LoadAsync(password, path);

            Assert.Equal(network, safe.Network);
            Debug.WriteLine($"Unique Safe ID: {safe.UniqueId}");

            // create walletjob
            WalletJob walletJob = new WalletJob();
            await walletJob.InitializeAsync(Helpers.SocksPortHandler, Helpers.ControlPortClient, safe, trackDefaultSafe : false, accountsToTrack : account);

            // note some event
            walletJob.ConnectedNodeCountChanged += WalletJob_ConnectedNodeCountChanged;
            walletJob.StateChanged += WalletJob_StateChanged;

            // start syncing
            var  cts           = new CancellationTokenSource();
            var  walletJobTask = walletJob.StartAsync(cts.Token);
            Task reportTask    = Helpers.ReportAsync(cts.Token, walletJob);

            try
            {
                // wait until blocks are synced
                while (walletJob.State <= WalletState.SyncingMemPool)
                {
                    await Task.Delay(1000);
                }

                foreach (var r in await walletJob.GetSafeHistoryAsync(account))
                {
                    Debug.WriteLine(r.TransactionId);
                }

                # region Basic

                var receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                var getBalanceResult = await walletJob.GetBalanceAsync(account);

                var   bal          = getBalanceResult.Available;
                Money amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                var   res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                           allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                var foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                _txProbArrived    = false;
                _prevCount        = (await walletJob.GetTrackerAsync()).TrackedTransactions.Count;
                _currentWalletJob = walletJob;
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;

                var sendRes = await walletJob.SendTransactionAsync(res.Transaction);

                Assert.True(sendRes.Success);
                Assert.Empty(sendRes.FailingReason);

                while (!_txProbArrived)
                {
                    Debug.WriteLine("Waiting for transaction...");
                    await Task.Delay(1000);
                }

                Debug.WriteLine("TrackedTransactions collection changed");
                Assert.Contains((await walletJob.GetTrackerAsync()).TrackedTransactions, x => x.Transaction.GetHash() == res.Transaction.GetHash());
                Debug.WriteLine("Transaction arrived");


                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                bal          = (await walletJob.GetBalanceAsync(account)).Available;
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;

                #endregion

                #region SubtractFeeFromAmount

                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                getBalanceResult = await walletJob.GetBalanceAsync(account);

                bal          = getBalanceResult.Available;
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                     allowUnconfirmed : true,
                                                                     subtractFeeFromAmount : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend - res.Fee, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend - res.Fee, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region CustomChange

                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();
                var customChange = new Key().ScriptPubKey;

                getBalanceResult = await walletJob.GetBalanceAsync(account);

                bal          = getBalanceResult.Available;
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                     allowUnconfirmed : true,
                                                                     subtractFeeFromAmount : true,
                                                                     customChangeScriptPubKey : customChange);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend - res.Fee, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Equal(customChange, res.ChangeOutput.ScriptPubKey);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend - res.Fee, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region LowFee

                res = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                            allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region MediumFee

                res = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Medium, account,
                                                            allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region HighFee

                res = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.High, account,
                                                            allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Equal(amountToSend, res.ActiveOutput.Value);
                Assert.NotNull(res.ChangeOutput);
                Assert.Contains(res.Transaction.Outputs, x => x.Value == res.ChangeOutput.Value);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"Change Output: {res.ChangeOutput.Value.ToString(false, true)} {res.ChangeOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                Assert.InRange(res.Fee, Money.Zero, res.Fee);
                Assert.InRange(res.Fee, res.Fee, res.Fee);

                _txProbArrived    = false;
                _prevCount        = (await walletJob.GetTrackerAsync()).TrackedTransactions.Count;
                _currentWalletJob = walletJob;
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;

                sendRes = await walletJob.SendTransactionAsync(res.Transaction);

                Assert.True(sendRes.Success);
                Assert.Empty(sendRes.FailingReason);

                while (_txProbArrived == false)
                {
                    Debug.WriteLine("Waiting for transaction...");
                    await Task.Delay(1000);
                }

                Debug.WriteLine("TrackedTransactions collection changed");
                Assert.Contains((await walletJob.GetTrackerAsync()).TrackedTransactions, x => x.Transaction.GetHash() == res.Transaction.GetHash());
                Debug.WriteLine("Transaction arrived");

                #endregion

                #region MaxAmount

                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                bal = (await walletJob.GetBalanceAsync(account)).Available;

                res = await walletJob.BuildTransactionAsync(receive, Money.Zero, FeeType.Low, account,
                                                            allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Null(res.ChangeOutput);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                Assert.Single(res.Transaction.Outputs);
                var maxBuiltTxOutput = res.Transaction.Outputs.Single();
                Assert.Equal(receive, maxBuiltTxOutput.ScriptPubKey);
                Assert.Equal(bal.Confirmed + bal.Unconfirmed - res.Fee, maxBuiltTxOutput.Value);

                #endregion

                #region InputSelection

                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                bal = (await walletJob.GetBalanceAsync(account)).Available;

                var inputCountBefore = res.SpentCoins.Count();
                res = await walletJob.BuildTransactionAsync(receive, Money.Zero, FeeType.Low, account,
                                                            allowUnconfirmed : true,
                                                            allowedInputs : res.SpentCoins.Where((x, i) => i == 0 || i % 2 == 0).Select(x => x.Outpoint));

                Assert.True(inputCountBefore >= res.SpentCoins.Count());
                Assert.Equal(res.SpentCoins.Count(), res.Transaction.Inputs.Count);
                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Assert.Equal(receive, res.ActiveOutput.ScriptPubKey);
                Assert.Null(res.ChangeOutput);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Active Output: {res.ActiveOutput.Value.ToString(false, true)} {res.ActiveOutput.ScriptPubKey.GetDestinationAddress(network)}");
                Debug.WriteLine($"TxId: {res.Transaction.GetHash()}");

                Assert.Single(res.Transaction.Outputs);

                res = await walletJob.BuildTransactionAsync(receive, Money.Zero, FeeType.Low, account,
                                                            allowUnconfirmed : true,
                                                            allowedInputs : new[] { res.SpentCoins.Select(x => x.Outpoint).First() });

                Assert.Single(res.Transaction.Inputs);
                Assert.Single(res.Transaction.Outputs);
                Assert.Single(res.SpentCoins);
                Assert.Null(res.ChangeOutput);

                #endregion
            }
예제 #2
0
        public async Task SendsFailGracefullyTestAsync()
        {
            Network      network  = Network.TestNet;
            SafeAccount  account  = new SafeAccount(1);
            string       path     = Path.Combine(Helpers.CommittedWalletsFolderPath, $"Sending{network}.json");
            const string password = "";
            Safe         safe     = await Safe.LoadAsync(password, path, network);

            Assert.Equal(network, safe.Network);
            Debug.WriteLine($"Unique Safe ID: {safe.UniqueId}");

            // create walletjob
            WalletJob walletJob = new WalletJob();
            await walletJob.InitializeAsync(Helpers.SocksPortHandler, Helpers.ControlPortClient, safe, trackDefaultSafe : false, accountsToTrack : account);

            // note some event
            walletJob.ConnectedNodeCountChanged += WalletJob_ConnectedNodeCountChanged;
            walletJob.StateChanged += WalletJob_StateChanged;

            // start syncing
            var  cts           = new CancellationTokenSource();
            var  walletJobTask = walletJob.StartAsync(cts.Token);
            Task reportTask    = Helpers.ReportAsync(cts.Token, walletJob);

            try
            {
                // wait until blocks are synced
                while (walletJob.State <= WalletState.SyncingMemPool)
                {
                    await Task.Delay(1000);
                }

                var history = await walletJob.GetSafeHistoryAsync(account);

                foreach (var record in history)
                {
                    Debug.WriteLine($"{record.TransactionId} {record.Amount} {record.Confirmed}");
                }

                var receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                var bal = (await walletJob.GetBalanceAsync(account)).Available;

                // Not enough fee
                Money amountToSend = (bal.Confirmed + bal.Unconfirmed) - new Money(1m, MoneyUnit.Satoshi);
                var   res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                           allowUnconfirmed : true);

                Assert.False(res.Success);
                Assert.NotEmpty(res.FailingReason);
                Debug.WriteLine($"Expected FailingReason: {res.FailingReason}");

                // That's not how you spend all
                amountToSend = (bal.Confirmed + bal.Unconfirmed);
                res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                     allowUnconfirmed : true);

                Assert.False(res.Success);
                Assert.NotEmpty(res.FailingReason);
                Debug.WriteLine($"Expected FailingReason: {res.FailingReason}");

                // Too much
                amountToSend = (bal.Confirmed + bal.Unconfirmed) + new Money(1, MoneyUnit.BTC);
                res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                     allowUnconfirmed : true);

                Assert.True(res.Success == false);
                Assert.True(res.FailingReason != "");
                Debug.WriteLine($"Expected FailingReason: {res.FailingReason}");

                // Minus
                amountToSend = new Money(-1m, MoneyUnit.BTC);
                res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                     allowUnconfirmed : true);

                Assert.False(res.Success);
                Assert.NotEmpty(res.FailingReason);
                Debug.WriteLine($"Expected FailingReason: {res.FailingReason}");

                // Default account is disabled
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                await Assert.ThrowsAsync <NotSupportedException>(async() => await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low,
                                                                                                                  allowUnconfirmed: true)).ContinueWith(t => {});

                // No such account
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                await Assert.ThrowsAsync <NotSupportedException>(async() => await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, new SafeAccount(23421),
                                                                                                                  allowUnconfirmed: true)).ContinueWith(t => { });
            }
            finally
            {
                cts?.Cancel();
                await Task.WhenAll(reportTask, walletJobTask);

                walletJob.ConnectedNodeCountChanged -= WalletJob_ConnectedNodeCountChanged;
                walletJob.StateChanged -= WalletJob_StateChanged;

                cts?.Dispose();
                reportTask?.Dispose();
                walletJobTask?.Dispose();
            }
        }
예제 #3
0
        private async Task UpdateHistoryRelatedMembersAsync()
        {
            // history
            var aliceHistory = (await _walletJob.GetSafeHistoryAsync(AliceAccount)).OrderByDescending(x => x.TimeStamp);
            var bobHistory   = (await _walletJob.GetSafeHistoryAsync(BobAccount)).OrderByDescending(x => x.TimeStamp);

            var hra = new List <HistoryRecordModel>();

            foreach (var rec in aliceHistory)
            {
                string height;
                if (rec.BlockHeight.Type == HeightType.Chain)
                {
                    height = rec.BlockHeight.Value.ToString();
                }
                else
                {
                    height = "";
                }

                hra.Add(new HistoryRecordModel {
                    Amount    = rec.Amount.ToString(true, true),
                    Confirmed = rec.Confirmed,
                    Height    = height,
                    TxId      = rec.TransactionId.ToString()
                });
            }
            _historyResponseAlice.History = hra.ToArray();

            var hrb = new List <HistoryRecordModel>();

            foreach (var rec in bobHistory)
            {
                string height;
                if (rec.BlockHeight.Type == HeightType.Chain)
                {
                    height = rec.BlockHeight.Value.ToString();
                }
                else
                {
                    height = "";
                }

                hrb.Add(new HistoryRecordModel
                {
                    Amount    = rec.Amount.ToString(true, true),
                    Confirmed = rec.Confirmed,
                    Height    = height,
                    TxId      = rec.TransactionId.ToString()
                });
            }
            _historyResponseBob.History = hrb.ToArray();

            // balances
            var getBalanceResult = await _walletJob.GetBalanceAsync(AliceAccount);

            var aa = getBalanceResult.Available;
            var getBalanceResult2 = await _walletJob.GetBalanceAsync(BobAccount);

            var ab = getBalanceResult2.Available;

            _availableAlice = aa.Confirmed;
            _incomingAlice  = aa.Unconfirmed;
            _availableBob   = ab.Confirmed;
            _incomingBob    = ab.Unconfirmed;

            // receive
            var ua = (await _walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, AliceAccount, HdPathType.Receive)).ToArray();
            var ub = (await _walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, BobAccount, HdPathType.Receive)).ToArray();

            _receiveResponseAlice.Addresses = new string[7];
            _receiveResponseBob.Addresses   = new string[7];
            var network = _walletJob.Safe.Network;

            for (int i = 0; i < 7; i++)
            {
                if (ua[i] != null)
                {
                    _receiveResponseAlice.Addresses[i] = ua[i].GetDestinationAddress(network).ToString();
                }
                else
                {
                    _receiveResponseAlice.Addresses[i] = "";
                }
                if (ub[i] != null)
                {
                    _receiveResponseBob.Addresses[i] = ub[i].GetDestinationAddress(network).ToString();
                }
                else
                {
                    _receiveResponseBob.Addresses[i] = "";
                }
            }

            _receiveResponseAlice.TraditionalAddress = (await _walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2PublicKeyHash, AliceAccount, HdPathType.Receive)).FirstOrDefault().GetDestinationAddress(network).ToString();
            _receiveResponseBob.TraditionalAddress   = (await _walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2PublicKeyHash, BobAccount, HdPathType.Receive)).FirstOrDefault().GetDestinationAddress(network).ToString();
        }
예제 #4
0
        public async Task SendTestAsync()
        {
            Network      network  = Network.TestNet;
            SafeAccount  account  = new SafeAccount(1);
            string       path     = Path.Combine(Helpers.CommittedWalletsFolderPath, $"Sending{network}.json");
            const string password = "";
            Safe         safe     = await Safe.LoadAsync(password, path);

            Assert.Equal(network, safe.Network);
            Debug.WriteLine($"Unique Safe ID: {safe.UniqueId}");

            // create walletjob
            WalletJob walletJob = new WalletJob();
            await walletJob.InitializeAsync(Helpers.SocksPortHandler, Helpers.ControlPortClient, safe, trackDefaultSafe : false, accountsToTrack : account);

            // note some event
            walletJob.ConnectedNodeCountChanged += WalletJob_ConnectedNodeCountChanged;
            walletJob.StateChanged += WalletJob_StateChanged;

            // start syncing
            var  cts           = new CancellationTokenSource();
            var  walletJobTask = walletJob.StartAsync(cts.Token);
            Task reportTask    = Helpers.ReportAsync(cts.Token, walletJob);

            try
            {
                // wait until blocks are synced
                while (walletJob.State <= WalletState.SyncingMemPool)
                {
                    await Task.Delay(1000);
                }

                foreach (var r in await walletJob.GetSafeHistoryAsync(account))
                {
                    Debug.WriteLine(r.TransactionId);
                }

                var record = (await walletJob.GetSafeHistoryAsync(account)).FirstOrDefault();
                Debug.WriteLine(record.Confirmed);
                Debug.WriteLine(record.Amount);

                var receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                var getBalanceResult = await walletJob.GetBalanceAsync(account);

                var   bal          = getBalanceResult.Available;
                Money amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;
                var   res          = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                           allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Transaction: {res.Transaction}");

                var foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                _txProbArrived    = false;
                _prevCount        = (await walletJob.GetTrackerAsync()).TrackedTransactions.Count;
                _currentWalletJob = walletJob;
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;

                var sendRes = await walletJob.SendTransactionAsync(res.Transaction);

                Assert.True(sendRes.Success);
                Assert.Empty(sendRes.FailingReason);

                while (!_txProbArrived)
                {
                    Debug.WriteLine("Waiting for transaction...");
                    await Task.Delay(1000);
                }

                Debug.WriteLine("TrackedTransactions collection changed");
                Assert.Contains((await walletJob.GetTrackerAsync()).TrackedTransactions, x => x.Transaction.GetHash() == res.Transaction.GetHash());
                Debug.WriteLine("Transaction arrived");


                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                bal          = (await walletJob.GetBalanceAsync(account)).Available;
                amountToSend = (bal.Confirmed + bal.Unconfirmed) / 2;

                #region LowFee

                var resLow = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Low, account,
                                                                   allowUnconfirmed : true);

                Assert.True(resLow.Success);
                Assert.Empty(resLow.FailingReason);
                Debug.WriteLine($"Fee: {resLow.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {resLow.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {resLow.SpendsUnconfirmed}");
                Debug.WriteLine($"Transaction: {resLow.Transaction}");

                foundReceive = false;
                Assert.InRange(resLow.Transaction.Outputs.Count, 1, 2);
                foreach (var output in resLow.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region MediumFee

                var resMedium = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.Medium, account,
                                                                      allowUnconfirmed : true);

                Assert.True(resMedium.Success);
                Assert.Empty(resMedium.FailingReason);
                Debug.WriteLine($"Fee: {resMedium.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {resMedium.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {resMedium.SpendsUnconfirmed}");
                Debug.WriteLine($"Transaction: {resMedium.Transaction}");

                foundReceive = false;
                Assert.InRange(resMedium.Transaction.Outputs.Count, 1, 2);
                foreach (var output in resMedium.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                #region HighFee

                var resHigh = await walletJob.BuildTransactionAsync(receive, amountToSend, FeeType.High, account,
                                                                    allowUnconfirmed : true);

                Assert.True(resHigh.Success);
                Assert.Empty(resHigh.FailingReason);
                Debug.WriteLine($"Fee: {resHigh.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {resHigh.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {resHigh.SpendsUnconfirmed}");
                Debug.WriteLine($"Transaction: {resHigh.Transaction}");

                foundReceive = false;
                Assert.InRange(resHigh.Transaction.Outputs.Count, 1, 2);
                foreach (var output in resHigh.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(amountToSend, output.Value);
                    }
                }
                Assert.True(foundReceive);

                #endregion

                Assert.InRange(resLow.Fee, Money.Zero, resMedium.Fee);
                Assert.InRange(resMedium.Fee, resLow.Fee, resHigh.Fee);

                _txProbArrived    = false;
                _prevCount        = (await walletJob.GetTrackerAsync()).TrackedTransactions.Count;
                _currentWalletJob = walletJob;
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;

                sendRes = await walletJob.SendTransactionAsync(resHigh.Transaction);

                Assert.True(sendRes.Success);
                Assert.Empty(sendRes.FailingReason);

                while (_txProbArrived == false)
                {
                    Debug.WriteLine("Waiting for transaction...");
                    await Task.Delay(1000);
                }

                Debug.WriteLine("TrackedTransactions collection changed");
                Assert.Contains((await walletJob.GetTrackerAsync()).TrackedTransactions, x => x.Transaction.GetHash() == resHigh.Transaction.GetHash());
                Debug.WriteLine("Transaction arrived");



                receive = (await walletJob.GetUnusedScriptPubKeysAsync(AddressType.Pay2WitnessPublicKeyHash, account, HdPathType.Receive)).FirstOrDefault();

                bal = (await walletJob.GetBalanceAsync(account)).Available;

                res = await walletJob.BuildTransactionAsync(receive, Money.Zero, FeeType.Low, account,
                                                            allowUnconfirmed : true);

                Assert.True(res.Success);
                Assert.Empty(res.FailingReason);
                Debug.WriteLine($"Fee: {res.Fee}");
                Debug.WriteLine($"FeePercentOfSent: {res.FeePercentOfSent} %");
                Debug.WriteLine($"SpendsUnconfirmed: {res.SpendsUnconfirmed}");
                Debug.WriteLine($"Transaction: {res.Transaction}");

                foundReceive = false;
                Assert.InRange(res.Transaction.Outputs.Count, 1, 2);
                foreach (var output in res.Transaction.Outputs)
                {
                    if (output.ScriptPubKey == receive)
                    {
                        foundReceive = true;
                        Assert.Equal(bal.Confirmed + bal.Unconfirmed - res.Fee, output.Value);
                    }
                }
                Assert.True(foundReceive);

                _txProbArrived    = false;
                _prevCount        = (await walletJob.GetTrackerAsync()).TrackedTransactions.Count;
                _currentWalletJob = walletJob;
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged += TrackedTransactions_CollectionChangedAsync;

                sendRes = await walletJob.SendTransactionAsync(res.Transaction);

                Assert.True(sendRes.Success);
                Assert.Empty(sendRes.FailingReason);

                while (_txProbArrived == false)
                {
                    Debug.WriteLine("Waiting for transaction...");
                    await Task.Delay(1000);
                }

                Debug.WriteLine("TrackedTransactions collection changed");
                Assert.Contains((await walletJob.GetTrackerAsync()).TrackedTransactions, x => x.Transaction.GetHash() == res.Transaction.GetHash());
                Debug.WriteLine("Transaction arrived");
            }
            finally
            {
                (await walletJob.GetTrackerAsync()).TrackedTransactions.CollectionChanged -= TrackedTransactions_CollectionChangedAsync;

                cts.Cancel();
                await Task.WhenAll(reportTask, walletJobTask);

                walletJob.ConnectedNodeCountChanged -= WalletJob_ConnectedNodeCountChanged;
                walletJob.StateChanged -= WalletJob_StateChanged;

                cts?.Dispose();
                reportTask?.Dispose();
                walletJobTask?.Dispose();
            }
        }