diff --git a/commands.py b/commands.py
index 9ae3bd7f722ad18aea00dff094d4e7115ba8117e..6fbe5dbd23748966dee3c7da353e2698b2bdcbc5 100644
--- a/commands.py
+++ b/commands.py
@@ -1,9 +1,15 @@
 import ast
+import os
+
+from bitcoinlib.encoding import EncodingError
+from bitcoinlib.keys import Address
+from bitcoinlib.wallets import Wallet
 from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
 from telegram.ext import CallbackContext
 
+import database
 from database import AppUser, AppState, AppWallet, AppWalletRequest, AppUserWallet
-from util import generate_wallets, get_wallet_name
+from util import generate_wallets, get_wallet_name, has_enough_funds, do_transaction
 
 
 def generate_message(state_id, extra_menu=None):
@@ -26,6 +32,7 @@ def start(update: Update, context: CallbackContext):
         token = params[1]
         request = AppWalletRequest.get(AppWalletRequest.token == token)
         user_wallet, created = AppUserWallet.get_or_create(user_id=user.id, wallet_id=request.wallet_id)
+        # TODO remove or True
         if created or True:
             request.delete_instance()
             update.effective_message.reply_text("Succesfully joined the wallet")
@@ -44,7 +51,7 @@ def start(update: Update, context: CallbackContext):
             update.effective_message.reply_text("You cannot join a wallet twice")
 
     user.set_state(1)
-    user.set_variable({})
+    user.set_variables({})
 
     reply_msg, reply_markup = generate_message(1)
     update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
@@ -64,7 +71,11 @@ def send_a_transaction(update: Update, context: CallbackContext):
     telegram_user = update.effective_user
     user, created = AppUser.get_or_create(telegram_id=telegram_user.id, nickname=telegram_user.full_name)
     if user.state_id.id != 6:
-        update.effective_message.reply_text("You cannot do this operation now")
+        update.effective_message.reply_text("You cannot do this operation right now")
+    else:
+        next_state = user.next_state()
+        reply_msg, reply_markup = generate_message(next_state)
+        update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
     pass
 
 
@@ -77,24 +88,88 @@ def create_wallet(update: Update, context: CallbackContext):
 
 
 def choose_wallet(update: Update, context: CallbackContext):
+    # TODO: some information about the wallet when choosing the wallet
+    # TODO: check if wallet is already created (choose wallet)
     telegram_user = update.effective_user
     user = AppUser.get(telegram_id=telegram_user.id, nickname=telegram_user.full_name)
     user_wallets = AppUserWallet.select().where(AppUserWallet.user_id == user)
     user.set_state(5)
-    menu = [[InlineKeyboardButton(uw.wallet_id.name, callback_data=get_wallet_name(uw.wallet_id.id, uw.user_id.id))] for uw in user_wallets]
+    menu = [[InlineKeyboardButton(uw.wallet_id.name, callback_data=uw.wallet_id.id)] for uw in user_wallets]
     reply_msg, reply_markup = generate_message(5, menu)
     update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
     pass
 
 
 def wallet_options(update: Update, context: CallbackContext, user: AppUser):
-    wallet_name = update.callback_query.data
-    user.set_variable("wallet_name", wallet_name)
+    wallet_id = update.callback_query.data
+    user.set_variable("wallet_id", wallet_id)
     next_state = user.next_state()
     reply_msg, reply_markup = generate_message(next_state)
     update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
 
 
+def transaction_address(update: Update, context: CallbackContext, user: AppUser):
+    msg = update.effective_message.text
+    try:
+        address = Address(msg, network=os.getenv("BTC_NETWORK"))
+        user.set_variable("address", msg)
+        next_state = user.next_state()
+        reply_msg, reply_markup = generate_message(next_state)
+        update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
+    except EncodingError:
+        update.effective_message.reply_text("This is not a valid address")
+
+
+def transaction_amount(update: Update, context: CallbackContext, user: AppUser):
+    msg = update.effective_message.text
+    try:
+        amount = float(msg)
+        user.set_variable("amount", amount)
+        next_state = user.next_state()
+        reply_msg, reply_markup = generate_message(next_state)
+        update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
+    except ValueError:
+        pass
+        # update.effective_message.reply_text("This is not a number, try again")
+
+
+def transaction_fee(update: Update, context: CallbackContext, user: AppUser):
+    cq = update.callback_query
+    cm = update.effective_message
+    success = False
+    if cq:
+        query = cq.data
+        if query == "low" or query == "normal" or query == "high":
+            user.set_variable("fee", query)
+            success = True
+
+    elif cm:
+        msg = cm.text
+        try:
+            amount = float(msg)
+            user.set_variable("fee", amount)
+            success = True
+        except ValueError:
+            pass
+
+    if success:
+        variables = user.variables()
+        t, has_funds, error = do_transaction(variables["wallet_id"], user.id, variables["address"], variables["amount"], variables["fee"])
+        if not has_funds:
+            update.effective_message.reply_text("The wallet does not have enough funds to do this transaction, please change the amount or fee")
+        elif error:
+            update.effective_message.reply_text("Something went wrong during the creating of the transaction please try again later")
+        else:
+            # TODO: send notification to the other co signers
+
+            pass
+            next_state = user.next_state()
+            reply_msg, reply_markup = generate_message(next_state)
+            update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
+    else:
+        update.effective_message.reply_text("Please send a number or use the buttons to identify the fee amount")
+
+
 def enter_co_signers(update: Update, context: CallbackContext, user: AppUser):
     msg = update.effective_message.text
     try:
@@ -171,7 +246,10 @@ def message_handler(update: Update, context: CallbackContext):
         2: enter_co_signers,
         3: minimum_co_signers,
         4: name_wallet,
-        5: wallet_options
+        5: wallet_options,
+        7: transaction_address,
+        8: transaction_amount,
+        9: transaction_fee
     }
     try:
         f = HANDLERS[state_user]
@@ -186,5 +264,5 @@ COMMANDS = {
     "create_a_wallet": create_wallet,
     "send_a_transaction": send_a_transaction,
     "back": back,
-    "choose_wallet": choose_wallet
+    "choose_wallet": choose_wallet,
 }
diff --git a/database.py b/database.py
index 8c47d2bad7c403d548e0417785a384271796b81c..b5ad49a336b17ba529c7af1bd88b33c28d5a2195 100644
--- a/database.py
+++ b/database.py
@@ -8,6 +8,7 @@ import os
 
 db = MySQLDatabase(None)
 
+
 def get_db_uri():
     user = os.getenv("DB_USER")
     password = os.getenv("DB_PASSWORD")
diff --git a/main.py b/main.py
index a57b5b093e6ac2291f2d5c30cd7990769103d613..2a668e7135ccc07b06909659e1d94628d53f171e 100644
--- a/main.py
+++ b/main.py
@@ -6,6 +6,7 @@ from database import connect
 
 load_dotenv()
 
+
 class TelegramWrapper:
     def __init__(self, token):
         self._token = token
diff --git a/util.py b/util.py
index 0fadef2a584976389c145ed9236ca61b696af74c..e7ee459aaf0081da2c4cca02f1f625578336b74a 100644
--- a/util.py
+++ b/util.py
@@ -2,10 +2,11 @@ import os
 
 from bitcoinlib.keys import HDKey
 from bitcoinlib.mnemonic import Mnemonic
-from bitcoinlib.wallets import Wallet
+from bitcoinlib.wallets import Wallet, WalletError
 
 import database
 
+
 def get_wallet_name(wallet_id, user_id):
     return "wallet_{}user_{}".format(wallet_id, user_id)
 
@@ -27,7 +28,7 @@ def generate_wallets(user_wallets):
     wallets = []
     for i in range(count):
         uw = user_wallets[i]
-        wallet_name = get_wallet_name(uw.wallet_id.id,uw.user_id.id)
+        wallet_name = get_wallet_name(uw.wallet_id.id, uw.user_id.id)
         wallet = Wallet.create(wallet_name,
                                sigs_required=uw.wallet_id.min_co_signers,
                                keys=generate_klist(hd_keys, i),
@@ -35,3 +36,20 @@ def generate_wallets(user_wallets):
                                db_uri=database.get_db_uri())
         wallets.append(wallet)
     return wallets, mnemonics
+
+
+def do_transaction(wallet_id, user_id, address, amount, fee):
+    wallet = Wallet(get_wallet_name(wallet_id, user_id), db_uri=os.getenv("BTC_NETWORK"))
+    wallet.utxos_update()
+    has_enough_funds = True
+    error = False
+    try:
+        t = wallet.send_to(to_address=address, fee=fee, network=os.getenv("BTC_NETWORK"), amount=amount)
+        t.sign()
+        return t, has_enough_funds, error
+    except WalletError as e:
+        error = True
+        if e.msg == "Not enough unspent transaction outputs found":
+            has_enough_funds = False
+
+    return None, has_enough_funds, error