Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
Bitcoin Telegram Bot
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
s2191814
Bitcoin Telegram Bot
Commits
7c250728
Commit
7c250728
authored
2 years ago
by
Dylan Janssen
Browse files
Options
Downloads
Patches
Plain Diff
Add: wallet creation is finished for now
parent
3284b37e
No related branches found
No related tags found
1 merge request
!2
Draft: initial user flow for creating a wallet
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
commands.py
+65
-13
65 additions, 13 deletions
commands.py
database.py
+15
-2
15 additions, 2 deletions
database.py
main.py
+0
-2
0 additions, 2 deletions
main.py
util.py
+31
-24
31 additions, 24 deletions
util.py
with
111 additions
and
41 deletions
commands.py
+
65
−
13
View file @
7c250728
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
}
This diff is collapsed.
Click to expand it.
database.py
+
15
−
2
View file @
7c250728
...
...
@@ -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
'
)
...
...
This diff is collapsed.
Click to expand it.
main.py
+
0
−
2
View file @
7c250728
...
...
@@ -6,8 +6,6 @@ from database import connect
load_dotenv
()
from
bitcoinlib.wallets
import
Wallet
class
TelegramWrapper
:
def
__init__
(
self
,
token
):
self
.
_token
=
token
...
...
This diff is collapsed.
Click to expand it.
util.py
+
31
−
24
View file @
7c250728
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
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment