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); }
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); }
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 ))); }