public void BuildTransferContext_SenderHasNoBalance_Fails()
        {
            string senderAddress = uint160.Zero.ToBase58Address(this.network);

            SmartContractTransactionService service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object);

            var request = new BuildContractTransactionRequest
            {
                AccountName = "account 0",
                WalletName  = "wallet",
                Password    = "******",
                Sender      = senderAddress,
            };

            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(new Features.Wallet.Wallet
            {
                AccountsRoot = new List <AccountRoot>
                {
                    new AccountRoot
                    {
                        Accounts = new List <HdAccount>
                        {
                            new HdAccount
                            {
                                ExternalAddresses = new List <HdAddress>
                                {
                                    new HdAddress
                                    {
                                        Address = senderAddress
                                    }
                                },
                                Name = request.AccountName,
                            }
                        }
                    }
                }
            });

            this.walletManager.Setup(x => x.GetAddressBalance(request.Sender))
            .Returns(new AddressBalance {
                Address = request.Sender, AmountConfirmed = 0, AmountUnconfirmed = 0
            });

            BuildContractTransactionResult result = service.BuildTx(request);

            Assert.Equal(SmartContractTransactionService.InsufficientBalanceError, result.Error);
            Assert.NotNull(result.Message);
            Assert.Null(result.Response);
        }
Beispiel #2
0
        public void BuildTransferContext_SenderHasNoBalance_Fails()
        {
            string senderAddress = uint160.Zero.ToBase58Address(this.network);

            var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object);

            var service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object,
                reserveUtxoService,
                this.blockStore.Object,
                this.chainIndexer,
                this.primitiveSerializer.Object,
                this.contractAssemblyCache.Object,
                this.receiptRepository.Object);

            var request = new BuildContractTransactionRequest
            {
                AccountName = "account 0",
                WalletName  = "wallet",
                Password    = "******",
                Sender      = senderAddress,
            };

            var wallet = new Features.Wallet.Wallet();

            wallet.AccountsRoot.Add(new AccountRoot(wallet));
            var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts)
            {
                Name = request.AccountName
            };

            account0.ExternalAddresses.Add(new HdAddress()
            {
                Address = senderAddress
            });

            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(wallet);

            this.walletManager.Setup(x => x.GetAddressBalance(request.Sender))
            .Returns(new AddressBalance {
                Address = request.Sender, AmountConfirmed = 0, AmountUnconfirmed = 0
            });

            BuildContractTransactionResult result = service.BuildTx(request);

            Assert.Equal(SmartContractTransactionService.InsufficientBalanceError, result.Error);
            Assert.NotNull(result.Message);
            Assert.Null(result.Response);
        }
        public void BuildTransferContext_AccountNotInWallet_Fails()
        {
            string senderAddress = uint160.Zero.ToBase58Address(this.network);

            SmartContractTransactionService service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object);

            var request = new BuildContractTransactionRequest
            {
                AccountName = "account 0",
                WalletName  = "wallet",
                Password    = "******",
                Sender      = senderAddress,
            };

            // Create a wallet but without the correct account name
            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(new Features.Wallet.Wallet
            {
                AccountsRoot = new List <AccountRoot>
                {
                    new AccountRoot
                    {
                        Accounts = new List <HdAccount>
                        {
                            new HdAccount
                            {
                                ExternalAddresses = new List <HdAddress>(),
                                Name = "account 1"
                            }
                        }
                    }
                }
            });

            BuildContractTransactionResult result = service.BuildTx(request);

            Assert.Equal(SmartContractTransactionService.AccountNotInWalletError, result.Error);
            Assert.NotNull(result.Message);
            Assert.Null(result.Response);
        }
Beispiel #4
0
        public void BuildTransferContext_AccountNotInWallet_Fails()
        {
            string senderAddress = uint160.Zero.ToBase58Address(this.network);

            var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object);

            var service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object,
                reserveUtxoService,
                this.blockStore.Object,
                this.chainIndexer,
                this.primitiveSerializer.Object,
                this.contractAssemblyCache.Object,
                this.receiptRepository.Object);

            var request = new BuildContractTransactionRequest
            {
                AccountName = "account 0",
                WalletName  = "wallet",
                Password    = "******",
                Sender      = senderAddress,
            };

            var wallet = new Features.Wallet.Wallet();

            wallet.AccountsRoot.Add(new AccountRoot(wallet));
            var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts)
            {
                Name = "account 1"
            };

            // Create a wallet but without the correct account name
            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(wallet);

            BuildContractTransactionResult result = service.BuildTx(request);

            Assert.Equal(SmartContractTransactionService.AccountNotInWalletError, result.Error);
            Assert.NotNull(result.Message);
            Assert.Null(result.Response);
        }
        public void BuildTransferContextCorrectly()
        {
            const int utxoIndex        = 0;
            uint256   utxoId           = uint256.Zero;
            uint256   utxoIdUnused     = uint256.One;
            string    senderAddress    = uint160.Zero.ToBase58Address(this.network);
            string    recipientAddress = uint160.One.ToBase58Address(this.network);
            string    changeAddress    = new uint160(2).ToBase58Address(this.network);

            var amount = 1234.567M;

            var request = new BuildContractTransactionRequest
            {
                AccountName      = "account 0",
                FeeAmount        = "0.01",
                WalletName       = "wallet",
                Password         = "******",
                Sender           = senderAddress,
                ShuffleOutputs   = true,
                AllowUnconfirmed = true,
                ChangeAddress    = changeAddress,
                Recipients       = new List <RecipientModel>
                {
                    // In locales that use a , for the decimal point this would fail to be parsed unless we use the invariant culture
                    new RecipientModel {
                        Amount = amount.ToString(CultureInfo.InvariantCulture), DestinationAddress = recipientAddress
                    }
                }
            };

            var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object);

            var service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object,
                reserveUtxoService);

            var senderHdAddress = new HdAddress {
                Address = senderAddress
            };

            var wallet = new Features.Wallet.Wallet();

            wallet.AccountsRoot.Add(new AccountRoot(wallet));
            var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts)
            {
                Name = request.AccountName
            };

            account0.ExternalAddresses.Add(new HdAddress()
            {
                Address = senderAddress
            });

            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(wallet);

            this.walletManager.Setup(x => x.GetAddressBalance(request.Sender))
            .Returns(new AddressBalance {
                Address = request.Sender, AmountConfirmed = Money.FromUnit(amount, MoneyUnit.BTC), AmountUnconfirmed = 0
            });

            var outputs = new List <UnspentOutputReference>
            {
                new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoId,
                        Index = utxoIndex,
                    }
                }, new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoIdUnused,
                        Index = utxoIndex,
                    }
                }
            };

            this.walletManager.Setup(x => x.GetSpendableTransactionsInWallet(It.IsAny <string>(), 0)).Returns(outputs);

            this.walletTransactionHandler.Setup(x => x.BuildTransaction(It.IsAny <TransactionBuildContext>()))
            .Returns(new Transaction());

            BuildContractTransactionResult result = service.BuildTx(request);

            // Check that the transaction builder is invoked, and that we:
            // - Ignore shuffleOutputs,
            // - Set inputs from sender
            // - Set recipients,
            // - Set change to sender
            this.walletTransactionHandler.Verify(w => w.BuildTransaction(It.Is <TransactionBuildContext>(context =>
                                                                                                         context.AllowOtherInputs == false &&
                                                                                                         context.Shuffle == false &&
                                                                                                         context.SelectedInputs.All(i => outputs.Select(o => o.Transaction.Id).Contains(i.Hash)) &&
                                                                                                         context.Recipients.Single().Amount == Money.FromUnit(amount, MoneyUnit.BTC) &&
                                                                                                         context.ChangeAddress.Address == senderHdAddress.Address
                                                                                                         )));
        }
        public void BuildTransferContext_RecipientIsKnownContract_Fails()
        {
            const int utxoIndex        = 0;
            uint256   utxoId           = uint256.Zero;
            uint256   utxoIdUnused     = uint256.One;
            string    senderAddress    = uint160.Zero.ToBase58Address(this.network);
            string    recipientAddress = uint160.One.ToBase58Address(this.network);

            var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object);

            var service = new SmartContractTransactionService(
                this.network,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object,
                reserveUtxoService);

            var request = new BuildContractTransactionRequest
            {
                AccountName = "account 0",
                WalletName  = "wallet",
                Password    = "******",
                Sender      = senderAddress,
                Recipients  = new List <RecipientModel>
                {
                    new RecipientModel {
                        Amount = "1", DestinationAddress = recipientAddress
                    }
                }
            };

            var wallet = new Features.Wallet.Wallet();

            wallet.AccountsRoot.Add(new AccountRoot(wallet));
            var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts)
            {
                Name = request.AccountName
            };

            account0.ExternalAddresses.Add(new HdAddress()
            {
                Address = senderAddress
            });

            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(wallet);

            this.walletManager.Setup(x => x.GetAddressBalance(request.Sender))
            .Returns(new AddressBalance {
                Address = request.Sender, AmountConfirmed = 10, AmountUnconfirmed = 0
            });

            this.walletManager.Setup(x => x.GetSpendableTransactionsInWallet(It.IsAny <string>(), 0))
            .Returns(new List <UnspentOutputReference>
            {
                new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoId,
                        Index = utxoIndex,
                    }
                }, new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoIdUnused,
                        Index = utxoIndex,
                    }
                }
            });

            this.stateRepository.Setup(s => s.IsExist(It.IsAny <uint160>())).Returns(true);

            BuildContractTransactionResult result = service.BuildTx(request);

            Assert.Equal(SmartContractTransactionService.TransferFundsToContractError, result.Error);
            Assert.NotNull(result.Message);
            Assert.Null(result.Response);
        }
        public void BuildTransferContext_Recipient_Is_Not_P2PKH()
        {
            const int utxoIndex     = 0;
            uint256   utxoId        = uint256.Zero;
            uint256   utxoIdUnused  = uint256.One;
            string    senderAddress = uint160.Zero.ToBase58Address(this.network);
            string    changeAddress = new uint160(2).ToBase58Address(this.network);

            // This is a valid non-P2PKH address on CirrusTest.
            string recipientAddress = "xH1GHWVNKwdebkgiFPtQtM4qb3vrvNX2Rg";
            var    cirrusNetwork    = CirrusNetwork.NetworksSelector.Testnet();

            var amount = 1234.567M;

            var request = new BuildContractTransactionRequest
            {
                AccountName      = "account 0",
                FeeAmount        = "0.01",
                WalletName       = "wallet",
                Password         = "******",
                Sender           = senderAddress,
                ShuffleOutputs   = true,
                AllowUnconfirmed = true,
                ChangeAddress    = changeAddress,
                Recipients       = new List <RecipientModel>
                {
                    new RecipientModel {
                        Amount = amount.ToString(), DestinationAddress = recipientAddress
                    }
                }
            };

            SmartContractTransactionService service = new SmartContractTransactionService(
                cirrusNetwork,
                this.walletManager.Object,
                this.walletTransactionHandler.Object,
                this.stringSerializer.Object,
                this.callDataSerializer.Object,
                this.addressGenerator.Object,
                this.stateRepository.Object);

            var senderHdAddress = new HdAddress {
                Address = senderAddress
            };

            this.walletManager.Setup(x => x.GetWallet(request.WalletName))
            .Returns(new Features.Wallet.Wallet
            {
                AccountsRoot = new List <AccountRoot>
                {
                    new AccountRoot
                    {
                        Accounts = new List <HdAccount>
                        {
                            new HdAccount
                            {
                                ExternalAddresses = new List <HdAddress>
                                {
                                    senderHdAddress
                                },
                                Name = request.AccountName,
                            }
                        }
                    }
                }
            });

            this.walletManager.Setup(x => x.GetAddressBalance(request.Sender))
            .Returns(new AddressBalance {
                Address = request.Sender, AmountConfirmed = Money.FromUnit(amount, MoneyUnit.BTC), AmountUnconfirmed = 0
            });

            var outputs = new List <UnspentOutputReference>
            {
                new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoId,
                        Index = utxoIndex,
                    }
                }, new UnspentOutputReference
                {
                    Address = new HdAddress
                    {
                        Address = senderAddress
                    },
                    Transaction = new TransactionData
                    {
                        Id    = utxoIdUnused,
                        Index = utxoIndex,
                    }
                }
            };

            this.walletManager.Setup(x => x.GetSpendableTransactionsInWallet(It.IsAny <string>(), 0)).Returns(outputs);

            this.walletTransactionHandler.Setup(x => x.BuildTransaction(It.IsAny <TransactionBuildContext>()))
            .Returns(new Transaction());

            BuildContractTransactionResult result = service.BuildTx(request);

            // Check that the transaction builder is invoked, and that we:
            // - Ignore shuffleOutputs,
            // - Set inputs from sender
            // - Set recipients,
            // - Set change to sender
            this.walletTransactionHandler.Verify(w => w.BuildTransaction(It.Is <TransactionBuildContext>(context =>
                                                                                                         context.AllowOtherInputs == false &&
                                                                                                         context.Shuffle == false &&
                                                                                                         context.SelectedInputs.All(i => outputs.Select(o => o.Transaction.Id).Contains(i.Hash)) &&
                                                                                                         context.Recipients.Single().Amount == Money.FromUnit(amount, MoneyUnit.BTC) &&
                                                                                                         context.ChangeAddress == senderHdAddress
                                                                                                         )));
        }