Skip to content
Snippets Groups Projects
Commit 7c250728 authored by Dylan Janssen's avatar Dylan Janssen
Browse files

Add: wallet creation is finished for now

parent 3284b37e
No related branches found
No related tags found
1 merge request!2Draft: initial user flow for creating a wallet
import ast
import os
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CallbackContext
from database import AppUser, AppState, AppWallet, AppWalletRequest
from util import DBManager
from database import AppUser, AppState, AppWallet, AppWalletRequest, AppUserWallet
from util import generate_wallets
# dbmanager = DBManager()
def generate_message(state_id):
def generate_message(state_id, extra_menu=None):
if extra_menu is None:
extra_menu = []
state = AppState.get(AppState.id == state_id)
reply_msg = state.message
menu_string = ast.literal_eval(state.menu)
menu = [[InlineKeyboardButton(y[0], callback_data=y[1]) for y in x] for x in menu_string]
menu = extra_menu + [[InlineKeyboardButton(y[0], callback_data=y[1]) for y in x] for x in menu_string]
reply_markup = InlineKeyboardMarkup(menu)
return reply_msg, reply_markup
def start(update: Update, context: CallbackContext):
msg = update.effective_message.text
params = msg.split(" ")
telegram_user = update.effective_user
user, created = AppUser.get_or_create(telegram_id=telegram_user.id, nickname=telegram_user.full_name)
if len(params) == 2:
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)
if created or True:
request.delete_instance()
update.effective_message.reply_text("Succesfully joined the wallet")
count = AppWalletRequest.select().where(AppWalletRequest.wallet_id == request.wallet_id).count()
if count == 0:
user_wallets = AppUserWallet.select().where(AppUserWallet.wallet_id == request.wallet_id)
wallets, mnemonics = generate_wallets(user_wallets)
for i in range(user_wallets.count()):
user = user_wallets[i].user_id
wallet = user_wallets[i].wallet_id
context.bot.send_message(chat_id=user.telegram_id, text="A wallet has been created for you: {}\n"
"A mnemonic has been created for you, save this carefully:\n\n"
"{}".format(wallet.name, mnemonics[i]))
pass
else:
update.effective_message.reply_text("You cannot join a wallet twice")
# TODO. when the last one is added send mnemonics to users
user.set_state(1)
# TODO: clear variables
......@@ -42,6 +65,8 @@ def back(update: Update, context: CallbackContext):
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")
pass
......@@ -53,6 +78,24 @@ def create_wallet(update: Update, context: CallbackContext):
update.effective_message.reply_text(reply_msg, reply_markup=reply_markup)
def choose_wallet(update: Update, context: CallbackContext):
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=uw.wallet_id.name)] 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):
print("We are in the wallet options")
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 enter_co_signers(update: Update, context: CallbackContext, user: AppUser):
msg = update.effective_message.text
try:
......@@ -70,6 +113,9 @@ def minimum_co_signers(update: Update, context: CallbackContext, user: AppUser):
msg = update.effective_message.text
try:
min_signers = int(msg)
if user.all_variables['max_co_signers'] < min_signers:
update.effective_message.reply_text("Minimum signers cannot be smaller than the maximum signers, please try again")
return
user.set_variable('min_co_signers', min_signers)
next_state = user.next_state()
reply_msg, reply_markup = generate_message(next_state)
......@@ -87,9 +133,11 @@ def name_wallet(update: Update, context: CallbackContext, user: AppUser):
user.set_variable('wallet_name', msg)
variables = user.all_variables
app_wallet = AppWallet.create(max_co_signers=variables['max_co_signers'],
min_co_signers=variables['min_co_signers'],
initiator_user_id=user.id,
name=variables['wallet_name'])
min_co_signers=variables['min_co_signers'],
initiator_user_id=user.id,
name=variables['wallet_name'])
AppUserWallet.create(user_id=user.id, wallet_id=app_wallet.id)
wallet_requests = AppWalletRequest.generate_requests(variables['max_co_signers'] - 1, app_wallet.id)
update.effective_message.reply_text("Wallet is created, forward each of these messages to one co-signer")
......@@ -97,7 +145,7 @@ def name_wallet(update: Update, context: CallbackContext, user: AppUser):
for request in wallet_requests:
update.effective_message.reply_text("Hi, please join this wallet as co-signer.\n"
"Wallet name= {}\n"
"https://t.me/BitcoinLibTestbot$start={}".format(variables['wallet_name'], request["token"]))
"https://t.me/BitcoinLibTestbot?start={}".format(variables['wallet_name'], request["token"]))
next_state = user.next_state()
reply_msg, reply_markup = generate_message(next_state)
......@@ -111,6 +159,8 @@ def callback_handler(update: Update, context: CallbackContext):
f(update, context)
except KeyError:
# Current state does not have a message handler, so do nothing
# Try the message handler, to go to state function
message_handler(update, context)
pass
......@@ -121,7 +171,8 @@ def message_handler(update: Update, context: CallbackContext):
HANDLERS = {
2: enter_co_signers,
3: minimum_co_signers,
4: name_wallet
4: name_wallet,
5: wallet_options
}
try:
f = HANDLERS[state_user]
......@@ -136,4 +187,5 @@ COMMANDS = {
"create_a_wallet": create_wallet,
"send_a_transaction": send_a_transaction,
"back": back,
"choose_wallet": choose_wallet
}
......@@ -8,6 +8,20 @@ import os
db = MySQLDatabase(None)
def get_db_uri():
user = os.getenv("DB_USER")
password = os.getenv("DB_PASSWORD")
host = os.getenv("DB_HOST")
port = os.getenv("DB_PORT")
database = os.getenv("DB_DATABASE")
return "mysql://{}:{}@{}:{}/{}".format(
user,
password,
host,
port,
database
)
def connect(create_tables=False) -> None:
"""Initializes the database session and connects to the database
......@@ -61,7 +75,7 @@ class AppUser(BaseModel):
def set_variables(self, new_variables: dict):
AppUser.update({AppUser.variables: json.dumps(new_variables)}).where(AppUser.id == self.id).execute()
def set_variable(self,key , value):
def set_variable(self, key, value):
new_variables = self.all_variables
new_variables[key] = value
self.set_variables(new_variables)
......@@ -85,7 +99,6 @@ class AppWalletRequest(BaseModel):
return wallet_requests
class AppUserWallet(BaseModel):
user_id = ForeignKeyField(AppUser, backref='wallets')
wallet_id = ForeignKeyField(AppWallet, backref='wallets')
......
......@@ -6,8 +6,6 @@ from database import connect
load_dotenv()
from bitcoinlib.wallets import Wallet
class TelegramWrapper:
def __init__(self, token):
self._token = token
......
import os
from bitcoinlib.keys import HDKey
from bitcoinlib.mnemonic import Mnemonic
from bitcoinlib.wallets import Wallet
class DBManager:
def __init__(self):
self._user = os.getenv("DB_USER")
self._password = os.getenv("DB_PASSWORD")
self._host = os.getenv("DB_HOST")
self._port = os.getenv("DB_PORT")
self._database = os.getenv("DB_DATABASE")
@property
def db_uri(self):
return "mysql://{}:{}@{}:{}/{}".format(
self._user,
self._password,
self._host,
self._port,
self._database
)
def create_or_get_user(self, telegram_user):
# TODO: create a method that gets the user or creates a new one
# telegram_user.full_name and telegram_user.id can be used for this
pass
# TODO CREATE QUERIES HERE
import database
def generate_klist(hd_keys, private):
return [hd_keys[x] if x == private else hd_keys[x].public_master_multisig() for x in range(len(hd_keys))]
def generate_hd_keys(amount):
mnemonics = [Mnemonic().generate(strength=256, add_checksum=True) for i in range(amount)]
keys = [HDKey.from_passphrase(passphrase, network=os.getenv("BTC_NETWORK"), multisig=True) for passphrase in mnemonics]
return keys, mnemonics
pass
def generate_wallets(user_wallets):
count = user_wallets.count()
hd_keys, mnemonics = generate_hd_keys(count)
wallets = []
for i in range(count):
uw = user_wallets[i]
wallet_name = "wallet_{}user_{}_{}".format(uw.wallet_id, uw.user_id,i)
wallet = Wallet.create(wallet_name,
sigs_required=uw.wallet_id.min_co_signers,
keys=generate_klist(hd_keys, i),
network=os.getenv("BTC_NETWORK"),
db_uri=database.get_db_uri())
wallets.append(wallet)
return wallets, mnemonics
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment