Example #1
0
        public BuildCreateContractTransactionResponse BuildCreateTx(BuildCreateContractTransactionRequest request)
        {
            AddressBalance addressBalance = this.walletManager.GetAddressBalance(request.Sender);

            if (addressBalance.AmountConfirmed == 0 && addressBalance.AmountUnconfirmed == 0)
            {
                return(BuildCreateContractTransactionResponse.Failed(SenderNoBalanceError));
            }

            var selectedInputs = new List <OutPoint>();

            selectedInputs = this.walletManager.GetSpendableInputsForAddress(request.WalletName, request.Sender);

            ContractTxData txData;

            if (request.Parameters != null && request.Parameters.Any())
            {
                try
                {
                    object[] methodParameters = this.methodParameterStringSerializer.Deserialize(request.Parameters);
                    txData = new ContractTxData(ReflectionVirtualMachine.VmVersion, (Stratis.SmartContracts.RuntimeObserver.Gas)request.GasPrice, (Stratis.SmartContracts.RuntimeObserver.Gas)request.GasLimit, request.ContractCode.HexToByteArray(), methodParameters);
                }
                catch (MethodParameterStringSerializerException exception)
                {
                    return(BuildCreateContractTransactionResponse.Failed(exception.Message));
                }
            }
            else
            {
                txData = new ContractTxData(ReflectionVirtualMachine.VmVersion, (Stratis.SmartContracts.RuntimeObserver.Gas)request.GasPrice, (Stratis.SmartContracts.RuntimeObserver.Gas)request.GasLimit, request.ContractCode.HexToByteArray());
            }

            HdAddress senderAddress = null;

            if (!string.IsNullOrWhiteSpace(request.Sender))
            {
                Features.Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);
                HdAccount account             = wallet.GetAccountByCoinType(request.AccountName, this.coinType);
                if (account == null)
                {
                    return(BuildCreateContractTransactionResponse.Failed($"No account with the name '{request.AccountName}' could be found."));
                }

                senderAddress = account.GetCombinedAddresses().FirstOrDefault(x => x.Address == request.Sender);
            }

            ulong totalFee = (request.GasPrice * request.GasLimit) + Money.Parse(request.FeeAmount);
            var   walletAccountReference = new WalletAccountReference(request.WalletName, request.AccountName);

            byte[] serializedTxData = this.callDataSerializer.Serialize(txData);

            Result <ContractTxData> deserialized = this.callDataSerializer.Deserialize(serializedTxData);

            // We also want to ensure we're sending valid data: AKA it can be deserialized.
            if (deserialized.IsFailure)
            {
                return(BuildCreateContractTransactionResponse.Failed("Invalid data. If network requires code signing, check the code contains a signature."));
            }

            // HACK
            // If requiring a signature, also check the signature.
            if (this.network is ISignedCodePubKeyHolder holder)
            {
                var  signedTxData = (SignedCodeContractTxData)deserialized.Value;
                bool validSig     = new ContractSigner().Verify(holder.SigningContractPubKey, signedTxData.ContractExecutionCode, signedTxData.CodeSignature);

                if (!validSig)
                {
                    return(BuildCreateContractTransactionResponse.Failed("Signature in code does not come from required signing key."));
                }
            }

            var recipient = new Recipient {
                Amount = request.Amount ?? "0", ScriptPubKey = new Script(serializedTxData)
            };
            var context = new TransactionBuildContext(this.network)
            {
                AccountReference = walletAccountReference,
                TransactionFee   = totalFee,
                ChangeAddress    = senderAddress,
                SelectedInputs   = selectedInputs,
                MinConfirmations = MinConfirmationsAllChecks,
                WalletPassword   = request.Password,
                Recipients       = new[] { recipient }.ToList()
            };

            try
            {
                Transaction transaction     = this.walletTransactionHandler.BuildTransaction(context);
                uint160     contractAddress = this.addressGenerator.GenerateAddress(transaction.GetHash(), 0);
                return(BuildCreateContractTransactionResponse.Succeeded(transaction, context.TransactionFee, contractAddress.ToBase58Address(this.network)));
            }
            catch (Exception exception)
            {
                return(BuildCreateContractTransactionResponse.Failed(exception.Message));
            }
        }
        private BuildCallContractTransactionResponse BuildCallTx(BuildCallContractTransactionRequest request)
        {
            this.logger.LogTrace(request.ToString());

            AddressBalance addressBalance = this.walletManager.GetAddressBalance(request.Sender);

            if (addressBalance.AmountConfirmed == 0)
            {
                return(BuildCallContractTransactionResponse.Failed($"The 'Sender' address you're trying to spend from doesn't have a confirmed balance. Current unconfirmed balance: {addressBalance.AmountUnconfirmed}. Please check the 'Sender' address."));
            }

            var selectedInputs = new List <OutPoint>();

            selectedInputs = this.walletManager.GetSpendableTransactionsInWallet(request.WalletName, MinConfirmationsAllChecks).Where(x => x.Address.Address == request.Sender).Select(x => x.ToOutPoint()).ToList();

            ulong   gasPrice       = ulong.Parse(request.GasPrice);
            ulong   gasLimit       = ulong.Parse(request.GasLimit);
            uint160 addressNumeric = new Address(request.ContractAddress).ToUint160(this.network);

            SmartContractCarrier carrier;

            if (request.Parameters != null && request.Parameters.Any())
            {
                carrier = SmartContractCarrier.CallContract(ReflectionVirtualMachine.VmVersion, addressNumeric, request.MethodName, gasPrice, new Gas(gasLimit), request.Parameters);
            }
            else
            {
                carrier = SmartContractCarrier.CallContract(ReflectionVirtualMachine.VmVersion, addressNumeric, request.MethodName, gasPrice, new Gas(gasLimit));
            }

            HdAddress senderAddress = null;

            if (!string.IsNullOrWhiteSpace(request.Sender))
            {
                Features.Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);
                HdAccount account             = wallet.GetAccountByCoinType(request.AccountName, this.coinType);
                senderAddress = account.GetCombinedAddresses().FirstOrDefault(x => x.Address == request.Sender);
            }

            ulong totalFee = (gasPrice * gasLimit) + Money.Parse(request.FeeAmount);
            var   context  = new TransactionBuildContext(this.network)
            {
                AccountReference = new WalletAccountReference(request.WalletName, request.AccountName),
                TransactionFee   = totalFee,
                ChangeAddress    = senderAddress,
                SelectedInputs   = selectedInputs,
                MinConfirmations = MinConfirmationsAllChecks,
                WalletPassword   = request.Password,
                Recipients       = new[] { new Recipient {
                                               Amount = request.Amount, ScriptPubKey = new Script(carrier.Serialize())
                                           } }.ToList()
            };

            try
            {
                Transaction transaction = this.walletTransactionHandler.BuildTransaction(context);
                return(BuildCallContractTransactionResponse.Succeeded(request.MethodName, transaction, context.TransactionFee));
            }
            catch (Exception exception)
            {
                return(BuildCallContractTransactionResponse.Failed(exception.Message));
            }
        }
        public IActionResult GetAddressBalance(string address)
        {
            AddressBalance balance = this.walletManager.GetAddressBalance(address);

            return(this.Json(balance.AmountConfirmed.ToUnit(MoneyUnit.Satoshi)));
        }
Example #4
0
        private bool CheckBalance(string address)
        {
            AddressBalance addressBalance = this.walletManager.GetAddressBalance(address);

            return(!(addressBalance.AmountConfirmed == 0 && addressBalance.AmountUnconfirmed == 0));
        }
        private BuildCreateContractTransactionResponse BuildCreateTx(BuildCreateContractTransactionRequest request)
        {
            this.logger.LogTrace(request.ToString());

            AddressBalance addressBalance = this.walletManager.GetAddressBalance(request.Sender);

            if (addressBalance.AmountConfirmed == 0)
            {
                return(BuildCreateContractTransactionResponse.Failed($"The 'Sender' address you're trying to spend from doesn't have a confirmed balance. Current unconfirmed balance: {addressBalance.AmountUnconfirmed}. Please check the 'Sender' address."));
            }

            var selectedInputs = new List <OutPoint>();

            selectedInputs = this.walletManager.GetSpendableTransactionsInWallet(request.WalletName, MinConfirmationsAllChecks).Where(x => x.Address.Address == request.Sender).Select(x => x.ToOutPoint()).ToList();

            ulong gasPrice = ulong.Parse(request.GasPrice);
            ulong gasLimit = ulong.Parse(request.GasLimit);

            ContractTxData txData;

            if (request.Parameters != null && request.Parameters.Any())
            {
                var methodParameters = this.methodParameterStringSerializer.Deserialize(request.Parameters);
                txData = new ContractTxData(ReflectionVirtualMachine.VmVersion, (Gas)gasPrice, (Gas)gasLimit, request.ContractCode.HexToByteArray(), methodParameters);
            }
            else
            {
                txData = new ContractTxData(ReflectionVirtualMachine.VmVersion, (Gas)gasPrice, (Gas)gasLimit, request.ContractCode.HexToByteArray());
            }

            HdAddress senderAddress = null;

            if (!string.IsNullOrWhiteSpace(request.Sender))
            {
                Features.Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);
                HdAccount account             = wallet.GetAccountByCoinType(request.AccountName, this.coinType);
                senderAddress = account.GetCombinedAddresses().FirstOrDefault(x => x.Address == request.Sender);
            }

            ulong totalFee = (gasPrice * gasLimit) + Money.Parse(request.FeeAmount);
            var   walletAccountReference = new WalletAccountReference(request.WalletName, request.AccountName);
            var   recipient = new Recipient {
                Amount = request.Amount ?? "0", ScriptPubKey = new Script(this.callDataSerializer.Serialize(txData))
            };
            var context = new TransactionBuildContext(this.network)
            {
                AccountReference = walletAccountReference,
                TransactionFee   = totalFee,
                ChangeAddress    = senderAddress,
                SelectedInputs   = selectedInputs,
                MinConfirmations = MinConfirmationsAllChecks,
                WalletPassword   = request.Password,
                Recipients       = new[] { recipient }.ToList()
            };

            try
            {
                Transaction transaction     = this.walletTransactionHandler.BuildTransaction(context);
                uint160     contractAddress = this.addressGenerator.GenerateAddress(transaction.GetHash(), 0);
                return(BuildCreateContractTransactionResponse.Succeeded(transaction, context.TransactionFee, contractAddress.ToBase58Address(this.network)));
            }
            catch (Exception exception)
            {
                return(BuildCreateContractTransactionResponse.Failed(exception.Message));
            }
        }
Example #6
0
        public async Task <string> BuildTransactionAsync(Guid operationId, AddressBalance from, string toAddress, long amount)
        {
            var fromKeyPair = KeyPair.FromAddress(from.Address);
            var fromAccount = new Account(fromKeyPair, from.Sequence);

            var toKeyPair = KeyPair.FromAddress(toAddress);

            var transferableBalance = from.Balance - from.MinBalance;

            StellarBase.Operation operation;
            if (await _horizonService.AccountExists(toAddress))
            {
                if (amount <= transferableBalance)
                {
                    var asset = new StellarBase.Asset();
                    operation = new PaymentOperation.Builder(toKeyPair, asset, amount)
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
                else
                {
                    operation = new AccountMergeOperation.Builder(toKeyPair)
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
            }
            else
            {
                if (amount <= transferableBalance)
                {
                    operation = new CreateAccountOperation.Builder(toKeyPair, amount)
                                .SetSourceAccount(fromKeyPair)
                                .Build();
                }
                else
                {
                    throw new BusinessException($"Currently not possible to transfer entire balance to an unused account! Use a destination in existance. transferable={transferableBalance}");
                }
            }

            fromAccount.IncrementSequenceNumber();

            var tx = new StellarBase.Transaction.Builder(fromAccount)
                     .AddOperation(operation)
                     .Build();

            var xdr    = tx.ToXDR();
            var writer = new ByteWriter();

            StellarBase.Generated.Transaction.Encode(writer, xdr);
            var xdrBase64 = Convert.ToBase64String(writer.ToArray());

            var build = new TxBuild
            {
                OperationId = operationId,
                XdrBase64   = xdrBase64
            };
            await _buildRepository.AddAsync(build);

            return(xdrBase64);
        }