public void BuildFeeEstimationContext_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 ScTxFeeEstimateRequest { AccountName = "account 0", WalletName = "wallet", Sender = senderAddress, ShuffleOutputs = true, AllowUnconfirmed = true, ChangeAddress = changeAddress, Recipients = new List <RecipientModel> { new RecipientModel { Amount = amount.ToString(), DestinationAddress = recipientAddress } }, FeeType = "medium" }; 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()); EstimateFeeResult result = service.EstimateFee(request); // Check that the transaction builder is invoked, and that we: // - Ignore shuffleOutputs, // - Set inputs from sender // - Set recipients, // - Set change to sender // - Set the fee type correctly // - Set sign to false // - Set transaction fee to null this.walletTransactionHandler.Verify(w => w.EstimateFee(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 && context.Sign == false && context.TransactionFee == null && context.FeeType == FeeType.Medium ))); }
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> { new RecipientModel { Amount = amount.ToString(), DestinationAddress = recipientAddress } } }; 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 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 ))); }
public void CanChooseInputsForCall() { const int utxoIndex = 0; uint256 utxoId = uint256.Zero; uint256 utxoIdUnused = uint256.One; string senderAddress = uint160.Zero.ToBase58Address(this.network); string contractAddress = uint160.One.ToBase58Address(this.network); var request = new BuildCallContractTransactionRequest { Amount = "0", AccountName = "account 0", ContractAddress = contractAddress, FeeAmount = "0.01", GasLimit = 100_000, GasPrice = 100, MethodName = "TestMethod", WalletName = "wallet", Password = "******", Sender = senderAddress, Outpoints = new List <OutpointRequest> { new OutpointRequest { Index = utxoIndex, TransactionId = utxoId.ToString() }, } }; this.walletManager.Setup(x => x.GetAddressBalance(request.Sender)) .Returns(new AddressBalance { Address = senderAddress, AmountConfirmed = new Money(100, MoneyUnit.BTC) }); 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.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 } } } } }); SmartContractTransactionService service = new SmartContractTransactionService( this.network, this.walletManager.Object, this.walletTransactionHandler.Object, this.stringSerializer.Object, this.callDataSerializer.Object, this.addressGenerator.Object, this.stateRepository.Object); BuildCallContractTransactionResponse result = service.BuildCallTx(request); this.walletTransactionHandler.Verify(x => x.BuildTransaction(It.Is <TransactionBuildContext>(y => y.SelectedInputs.Count == 1))); }
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); 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, Recipients = new List <RecipientModel> { new RecipientModel { Amount = "1", DestinationAddress = recipientAddress } } }; 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 = 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 ChoosingInvalidInputFails() { const int utxoIndex = 0; uint256 utxoId = uint256.Zero; uint256 utxoIdUnused = uint256.One; string senderAddress = uint160.Zero.ToBase58Address(this.network); string contractAddress = uint160.One.ToBase58Address(this.network); var request = new BuildCallContractTransactionRequest { Amount = "0", AccountName = "account 0", ContractAddress = contractAddress, FeeAmount = "0.01", GasLimit = 100_000, GasPrice = 100, MethodName = "TestMethod", WalletName = "wallet", Password = "******", Sender = senderAddress, Outpoints = new List <OutpointRequest> { new OutpointRequest { Index = utxoIndex, TransactionId = new uint256(64).ToString() // A tx we don't have. }, } }; this.walletManager.Setup(x => x.GetAddressBalance(request.Sender)) .Returns(new AddressBalance { Address = senderAddress, AmountConfirmed = new Money(100, MoneyUnit.BTC) }); 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, } } }); SmartContractTransactionService service = new SmartContractTransactionService( this.network, this.walletManager.Object, this.walletTransactionHandler.Object, this.stringSerializer.Object, this.callDataSerializer.Object, this.addressGenerator.Object, this.stateRepository.Object); BuildCallContractTransactionResponse result = service.BuildCallTx(request); Assert.False(result.Success); Assert.StartsWith("Invalid list of request outpoints", result.Message); }