[Криптография, Python, SQLite, GitHub, Криптовалюты] Внедряем оплату BTC куда угодно (Python)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
ПредысторияПолгода назад взялся за один проект с возможностью оплаты биткойном. Так как проект делали на языке python, то и оплату хотелось реализовать на нем же. Сразу же взялся анализировать готовые решения, доступные библиотеки и Rest API Blockchain.com. С апи блокчейна я моментально обломался, так как их токен для использования апи довольно не просто получить.Затем решил юзать различные библиотеки (block-io, bitcoinlib, blockchain и др.) После пару ночей попыток реализовать нормальную оплату, остановился на bitcoinlib, так как она более менее стабильно работала, и я спокойно переводил с одного кошелька на другой. Беда наступила когда появились первые 100 пользователей и вся оплата внезапно рухнула. Возможно я криво написал или что-то не так понял с работой библиотеки, но любые попытки восстановить работу оплаты были безуспешны, только если обнулять бдшку, но и так неизвестно сколько бы она продержалась.
В итоге решили оставить без BTC оплаты. Я опечалился и не связывался с оплатой биткойном полгода.К чему я пришелНа днях я все-таки решил добить этот вопрос для себя, надеюсь кому-то еще пригодятся мои наработки.Все начинается с seed фразы. Мнемоническая фраза (англ. Mnemonic phrase или Seed фраза) - это список слов, которые хранят всю информацию, необходимую для восстановления биткоин-кошелька. Существуют несколько стандартов генерации фраз BIP 32, BIP 39, BIP 44, и еще BIP 49. Самый распространенный - это BIP 44 (12 слов). Пример seed фразы: vivid area able second bicycle advance demand alpha flip stable drift routeЧтобы сгенерировать фразу будем использовать библиотеку bipwallet. Чтобы ее установить воспользуемся командой pip install bipwallet.
from bipwallet import wallet
# generate 12 word mnemonic seed
seed = wallet.generate_mnemonic()
print(seed)
Если мы хотим получить напрямую доступ к биткойн кошельку, то, зная фразу, можем сразу восставновить кошелек в blockhain.com:https://login.blockchain.com/#/recover
Следующим шагом мы будем преобразовывать нашу seed фразу до получения нужного адреса кошелька биткойна.Чтобы во всем не запутаться и знать какие данные мы должны получить, я использовал сайт https://iancoleman.io/bip39/
Генерация дочернего адреса кошелька для каждого пользователя:Чтобы получить наш нулевой адрес Биткойн кошелька на основе seed фразы (12VeK1eRgPHRUikNLXq3Nuz99gS2S46QMD), нам нужно пройти всю цепочку преобразований. Методом проб и ошибок мне все-таки удалось получить адрес кошелька следующим кодом:
from bipwallet.utils import *
def gen_address(index):
# Наша seed фраза
seed = 'vivid area able second bicycle advance demand alpha flip stable drift route'
# Мастер ключ из seed фразы
master_key = HDPrivateKey.master_key_from_mnemonic(seed)
# Public key из мастер ключа по пути 'm/44/0/0/0'
root_keys = HDKey.from_path(master_key, "m/44'/0'/0'/0")[-1].public_key.to_b58check()
# Extended public key
xpublic_key = str(root_keys, encoding="utf-8")
# Адрес дочернего кошелька в зависимости от значения index
address = Wallet.deserialize(xpublic_key, network='BTC').get_child(index, is_prime=False).to_address()
rootkeys_wif = HDKey.from_path(master_key, f"m/44'/0'/0'/0/{index}")[-1]
# Extended private key
xprivatekey = str(rootkeys_wif.to_b58check(), encoding="utf-8")
# Wallet import format
wif = Wallet.deserialize(xprivatekey, network='BTC').export_to_wif()
return address, str(wif, 'utf-8')
print(gen_address(0))
Данная функция возвращает адрес кошелька и wif в зависимости номера. Максимальное число с которым удалось получить адрес это 999999999. wif (Wallet import format) - это просто кодирование байтов ключа в кодировку Base58 + контрольная сумма. Он нам понадобится в дальнейшем при генерации транзакции. Это все значит, что имея только одну seed фразу мы можем создать 1 млрд дочерних адресов. Каждому пользователю при регистрации мы будем выдавать новый адрес, через который он сможет оплачивать по BTC. Появляется ограничение на 1 млрд пользователей, но нам никто не запрещает использовать несколько seed фраз или генерировать каждому юзеру новую фразу, но тогда каждая оплата будет кидаться не в общий ваш кошелек, а по разным.Проверка баланса и транзакции:Теперь когда у каждого пользователя свой личный адрес биткойн кошелька, нужно проверить баланс этого адреса. Для этого мы будем обращаться к сайту Blockchain.com дабы получить нужную информацию.
import requests
# Адрес кошелька пользователя
wallet = '12VeK1eRgPHRUikNLXq3Nuz99gS2S46QMD'
# wallet = gen_address(0)
url = f'https://blockchain.info/rawaddr/{wallet}'
x = requests.get(url)
wallet = x.json()
print('Итоговый баланс:'+str(wallet['final_balance']))
print('Транзакции:'+str(wallet['txs']))
if wallet['total_received']==0:
print('баланс пустой')
Вот таким простым кодом мы можем получить всю информацию по балансу и транзакциях пользователя. Дальше все зависит от логики самого приложения. ТранзакцииНа данном этапе мы дали каждому пользователю свой адрес кошелька и знаем все транзакции с данным адресом, но этого недостаточно. Нам нужно чтобы мы могли отправить его же деньги обратно. Для этого воспользуемся библотекой bit. Чтобы ее установить воспользуемся командой pip install bit.
from bit import PrivateKey
# Приватный ключ из wif
my_key = PrivateKey(wif='L46ixenNSu8Bqk899ZrH8Y96t8DHqJ1ZyxzQBGFTbh38rLHLaPoY')
# Количество долларов перевода, можно поменять на btc
money=0.1
# Кошелек куда будут переведены деньги
wallet='17ya3bCpPioyPH8kAyFkEDBUqdjF6wwPxo'
# Коммисия перевода, если поставить слишком маленькую, то транзакцию не примут
# И чем больше коммисия, тем быстрее пройдет перевод
fee=2000
# Генерация транзакции
tx_hash = my_key.create_transaction([(wallet, money, 'usd')],fee=fee,absolute_fee=True)
print(tx_hash)
В итоге мы получили вот такую транзакцию:0100000001fe64490fce5e85d5eb00865663a3d44f4108549fdb2840b086cfc781390d4a2d010000006a47304402202dc1496d28bb10d50d94d70870e2a79ea472c5960de8f7418bb30f9b96643efc02204691547c98edad3181a056bf6404601efe289200ba8e3073a2f5b7c0c7f4fec10121026516c551584b484ce3ca7bb71bbf24cce133bf40bdf4e2ce5a3936bc7e66a2abffffffff02e3020000000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac08f40200000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac00000000Выглядит красиво, но что с этим делать? Можно зайти на сайт https://www.blockchain.com/btc/pushtx и вручную отправить эту транзакцию.
Также можем декодировать эту транзакцию и проверить все ли верно мы указали https://www.blockchain.com/btc/decode-tx
Но нам нужно это автоматизировать, поэтому напишем несколько строк:
import requests
url = 'https://blockchain.info/pushtx'
tx='0100000001fe64490fce5e85d5eb00865663a3d44f4108549fdb2840b086cfc781390d4a2d010000006a47304402202dc1496d28bb10d50d94d70870e2a79ea472c5960de8f7418bb30f9b96643efc02204691547c98edad3181a056bf6404601efe289200ba8e3073a2f5b7c0c7f4fec10121026516c551584b484ce3ca7bb71bbf24cce133bf40bdf4e2ce5a3936bc7e66a2abffffffff02e3020000000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac08f40200000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac00000000'
x = requests.post(url, data = {'tx':tx})
result = x.text
print(result)
Выполним пост запрос, если получаем ответ: Transaction Submitted. Это значит, что через несколько секунд транзакция появится в сети и деньги спишутся с пользователя.ПрименениеНу чтож, написав всего несколько десятков строк, мы можем генерировать для каждого пользователя свой адрес кошелка, проверять его баланс, переводить биткойны с одного кошелька на любой другой. Для демонстрации работы BTC оплаты, я напишу простенького телеграм бота, который будет выполнять роль клиента Blockchain.com, то есть вы сможете хранить в нем свои биткойны и от туда же переводить другим людям. Ссылка на исходники бота будут в конце.Проверить работу бота можно тут: https://t.me/Blockchain_client_botЗадеплоил на heroku, так что надеюсь не будет падать)Функционал ботаРегистрация пользователя
В качестве БД я использовал sqlite3 и создал одну таблицу пользователей:
import sqlite3
conn = sqlite3.connect("my.db") # или :memory: чтобы сохранить в RAM
cursor = conn.cursor()
cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, balance INTEGER, btc_wallet TEXT, wif TEXT, btc_sent TEXT, state INTEGER)")
conn.commit()
При нажатии start мы регистрируем пользователя, генерируем для него адрес биткойн кошелька, wif и добавляем данные в БД:
sql = "SELECT COUNT(*) FROM users "
cursor.execute(sql)
user = cursor.fetchone()
address, wif= gen_address(user[0]+1)
sql_insert = "INSERT INTO users VALUES ({}, '{}', 0,'{}','{}','no',0)".format(message.chat.id,
message.chat.first_name,address,wif)
cursor.execute(sql_insert)
conn.commit()
Проверка баланса
if message.text == '? Ваш баланс':
url = f'https://blockchain.info/rawaddr/{data[3]}'
x = requests.get(url)
wallet = x.json()
await bot.send_message(message.chat.id, f'''? *Итоговый баланс:* {format(wallet['final_balance'] / 100000000, '.9f')} BTC
*Всего получено:* {format(wallet['total_received'] / 100000000, '.9f')} BTC
*Всего отправлено:* {format(wallet['total_sent'] / 100000000, '.9f')} BTC
https://www.blockchain.com/ru/btc/address/{data[3]}''', parse_mode= "Markdown")
Получить BTC
Для создания qr-кода я использовал библиотеку qrcode и на вход передал ранее сгенерированный адрес биткойн кошелька из БД.
if message.text == '? Получить BTC':
img = qrcode.make(data[3])
img.save('qr.jpg')
await bot.send_message(message.chat.id, f'''? Ваш адрес биткойн кошелька:
*{data[3]}*''', parse_mode= "Markdown")
await bot.send_photo(message.chat.id,photo=open('qr.jpg', 'rb'))
Отправить BTC
try:
sum = float(message.text)
url = f'https://blockchain.info/rawaddr/{data[3]}'
x = requests.get(url)
wallet = x.json()
if sum + 10000 <= wallet['final_balance'] / 100000000:
try:
my_key = PrivateKey(wif=data[4])
# Коммисия перевода, если поставить слишком маленькую, то транзакцию не примут
# И чем больше коммисия, тем быстрее пройдет перевод
fee = 10000
# Генерация транзакции
tx_hash = my_key.create_transaction([(data[5], sum, 'btc')], fee=fee, absolute_fee=True)
print(tx_hash)
url = 'https://blockchain.info/pushtx'
x = requests.post(url, data={'tx': tx_hash})
result = x.text
sql = "UPDATE users SET state = {} WHERE chatid = {}".format(0, message.chat.id)
cursor.execute(sql)
conn.commit()
await bot.send_message(message.chat.id, result)
except Exception:
await bot.send_message(message.chat.id, "⚠ Ошибка при выолнении транзакции")
else:
await bot.send_message(message.chat.id, '⚠️ На вашем балансе недостаточно средств.')
except ValueError:
await bot.send_message(message.chat.id, '⚠️Неправильно введена сумма отправления, попробуйте еще раз')
Проверим через сайт, что транзакция отправилась:
Исходники и как запустить Скачать исходники бота можно тут github.com/Lil-hack/blockchain-client Склонировав репозиторий, устанавливаем необходимые пакеты:pip install -r requirements.txtНекоторые библиотеки у меня не заработали на windows, так что лучше сразу запускать на linux. В файле main.py заменяем ваш токен телеграм бота:
# Ваш токен от BotFather
TOKEN = 'YOUR TOKEN'
В файле btc_core.py заменяем на вашу seed фразу:
# Ваша seed фраза
seed = 'YOUR SEED'
И запускаем бота командой: python main.pyРаботает на python 3.7.0 и выше. Бот написан за один вечер, так что просьба строго не судить ^^ИтогоКак оказалось, все довольно не сложно, и в несколько десятков строк можно добавить оплату BTC в любой python проект. Я не профи в криптографии, так что скорее всего многие моменты упустил, но надеюсь кому-то эта статья будет полезна.
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, Поисковые технологии, Python, Программирование] Делаем поиск в веб-приложении с нуля
- [Машинное обучение, Исследования и прогнозы в IT, Финансы в IT, Транспорт] Как оптимизировать работу аэропортов с помощью машинного обучения
- [Python] Мелкая питонячая радость #12: вирусы и зловредное ПО на Python
- [Python, Машинное обучение, Социальные сети и сообщества] Toxic Comments Detection in Russian
- [Python, Машинное обучение, Искусственный интеллект, Natural Language Processing] Команда МФТИ второй год подряд в конкурсе от Amazon — Alexa Prize Socialbot Grand Challenge 4
- [Разработка веб-сайтов, Python] Забываете передавать аргументы в функцию? Вам поможет contextvars
- [Open source, GitHub, Законодательство в IT, IT-компании] Исходные коды GitHub.com и GitHub Enterprise утекли
- [Разработка под e-commerce, Управление e-commerce, Аналитика мобильных приложений] Онлайн Магазин будущего
- [Python, Java] Удав укрощает Graal VM
- [Информационная безопасность, Мессенджеры, Социальные сети и сообщества] 2FA в Telegram не везде, где хотелось бы
Теги для поиска: #_kriptografija (Криптография), #_python, #_sqlite, #_github, #_kriptovaljuty (Криптовалюты), #_btc, #_bitcoin, #_blockchain, #_telegram, #_telegram_bots, #_oplata (оплата), #_kriptovaljuta (криптовалюта), #_kriptografija (криптография), #_kriptografija (
Криптография
), #_python, #_sqlite, #_github, #_kriptovaljuty (
Криптовалюты
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:23
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
ПредысторияПолгода назад взялся за один проект с возможностью оплаты биткойном. Так как проект делали на языке python, то и оплату хотелось реализовать на нем же. Сразу же взялся анализировать готовые решения, доступные библиотеки и Rest API Blockchain.com. С апи блокчейна я моментально обломался, так как их токен для использования апи довольно не просто получить.Затем решил юзать различные библиотеки (block-io, bitcoinlib, blockchain и др.) После пару ночей попыток реализовать нормальную оплату, остановился на bitcoinlib, так как она более менее стабильно работала, и я спокойно переводил с одного кошелька на другой. Беда наступила когда появились первые 100 пользователей и вся оплата внезапно рухнула. Возможно я криво написал или что-то не так понял с работой библиотеки, но любые попытки восстановить работу оплаты были безуспешны, только если обнулять бдшку, но и так неизвестно сколько бы она продержалась. В итоге решили оставить без BTC оплаты. Я опечалился и не связывался с оплатой биткойном полгода.К чему я пришелНа днях я все-таки решил добить этот вопрос для себя, надеюсь кому-то еще пригодятся мои наработки.Все начинается с seed фразы. Мнемоническая фраза (англ. Mnemonic phrase или Seed фраза) - это список слов, которые хранят всю информацию, необходимую для восстановления биткоин-кошелька. Существуют несколько стандартов генерации фраз BIP 32, BIP 39, BIP 44, и еще BIP 49. Самый распространенный - это BIP 44 (12 слов). Пример seed фразы: vivid area able second bicycle advance demand alpha flip stable drift routeЧтобы сгенерировать фразу будем использовать библиотеку bipwallet. Чтобы ее установить воспользуемся командой pip install bipwallet. from bipwallet import wallet
# generate 12 word mnemonic seed seed = wallet.generate_mnemonic() print(seed) Следующим шагом мы будем преобразовывать нашу seed фразу до получения нужного адреса кошелька биткойна.Чтобы во всем не запутаться и знать какие данные мы должны получить, я использовал сайт https://iancoleman.io/bip39/ Генерация дочернего адреса кошелька для каждого пользователя:Чтобы получить наш нулевой адрес Биткойн кошелька на основе seed фразы (12VeK1eRgPHRUikNLXq3Nuz99gS2S46QMD), нам нужно пройти всю цепочку преобразований. Методом проб и ошибок мне все-таки удалось получить адрес кошелька следующим кодом: from bipwallet.utils import *
def gen_address(index): # Наша seed фраза seed = 'vivid area able second bicycle advance demand alpha flip stable drift route' # Мастер ключ из seed фразы master_key = HDPrivateKey.master_key_from_mnemonic(seed) # Public key из мастер ключа по пути 'm/44/0/0/0' root_keys = HDKey.from_path(master_key, "m/44'/0'/0'/0")[-1].public_key.to_b58check() # Extended public key xpublic_key = str(root_keys, encoding="utf-8") # Адрес дочернего кошелька в зависимости от значения index address = Wallet.deserialize(xpublic_key, network='BTC').get_child(index, is_prime=False).to_address() rootkeys_wif = HDKey.from_path(master_key, f"m/44'/0'/0'/0/{index}")[-1] # Extended private key xprivatekey = str(rootkeys_wif.to_b58check(), encoding="utf-8") # Wallet import format wif = Wallet.deserialize(xprivatekey, network='BTC').export_to_wif() return address, str(wif, 'utf-8') print(gen_address(0)) import requests
# Адрес кошелька пользователя wallet = '12VeK1eRgPHRUikNLXq3Nuz99gS2S46QMD' # wallet = gen_address(0) url = f'https://blockchain.info/rawaddr/{wallet}' x = requests.get(url) wallet = x.json() print('Итоговый баланс:'+str(wallet['final_balance'])) print('Транзакции:'+str(wallet['txs'])) if wallet['total_received']==0: print('баланс пустой') from bit import PrivateKey
# Приватный ключ из wif my_key = PrivateKey(wif='L46ixenNSu8Bqk899ZrH8Y96t8DHqJ1ZyxzQBGFTbh38rLHLaPoY') # Количество долларов перевода, можно поменять на btc money=0.1 # Кошелек куда будут переведены деньги wallet='17ya3bCpPioyPH8kAyFkEDBUqdjF6wwPxo' # Коммисия перевода, если поставить слишком маленькую, то транзакцию не примут # И чем больше коммисия, тем быстрее пройдет перевод fee=2000 # Генерация транзакции tx_hash = my_key.create_transaction([(wallet, money, 'usd')],fee=fee,absolute_fee=True) print(tx_hash) Также можем декодировать эту транзакцию и проверить все ли верно мы указали https://www.blockchain.com/btc/decode-tx Но нам нужно это автоматизировать, поэтому напишем несколько строк: import requests
url = 'https://blockchain.info/pushtx' tx='0100000001fe64490fce5e85d5eb00865663a3d44f4108549fdb2840b086cfc781390d4a2d010000006a47304402202dc1496d28bb10d50d94d70870e2a79ea472c5960de8f7418bb30f9b96643efc02204691547c98edad3181a056bf6404601efe289200ba8e3073a2f5b7c0c7f4fec10121026516c551584b484ce3ca7bb71bbf24cce133bf40bdf4e2ce5a3936bc7e66a2abffffffff02e3020000000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac08f40200000000001976a9144c83a20250ccb62ce2b3b1ea80c6082b634fdf9f88ac00000000' x = requests.post(url, data = {'tx':tx}) result = x.text print(result) В качестве БД я использовал sqlite3 и создал одну таблицу пользователей: import sqlite3
conn = sqlite3.connect("my.db") # или :memory: чтобы сохранить в RAM cursor = conn.cursor() cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, balance INTEGER, btc_wallet TEXT, wif TEXT, btc_sent TEXT, state INTEGER)") conn.commit() sql = "SELECT COUNT(*) FROM users "
cursor.execute(sql) user = cursor.fetchone() address, wif= gen_address(user[0]+1) sql_insert = "INSERT INTO users VALUES ({}, '{}', 0,'{}','{}','no',0)".format(message.chat.id, message.chat.first_name,address,wif) cursor.execute(sql_insert) conn.commit() if message.text == '? Ваш баланс':
url = f'https://blockchain.info/rawaddr/{data[3]}' x = requests.get(url) wallet = x.json() await bot.send_message(message.chat.id, f'''? *Итоговый баланс:* {format(wallet['final_balance'] / 100000000, '.9f')} BTC *Всего получено:* {format(wallet['total_received'] / 100000000, '.9f')} BTC *Всего отправлено:* {format(wallet['total_sent'] / 100000000, '.9f')} BTC https://www.blockchain.com/ru/btc/address/{data[3]}''', parse_mode= "Markdown") Для создания qr-кода я использовал библиотеку qrcode и на вход передал ранее сгенерированный адрес биткойн кошелька из БД. if message.text == '? Получить BTC':
img = qrcode.make(data[3]) img.save('qr.jpg') await bot.send_message(message.chat.id, f'''? Ваш адрес биткойн кошелька: *{data[3]}*''', parse_mode= "Markdown") await bot.send_photo(message.chat.id,photo=open('qr.jpg', 'rb')) try:
sum = float(message.text) url = f'https://blockchain.info/rawaddr/{data[3]}' x = requests.get(url) wallet = x.json() if sum + 10000 <= wallet['final_balance'] / 100000000: try: my_key = PrivateKey(wif=data[4]) # Коммисия перевода, если поставить слишком маленькую, то транзакцию не примут # И чем больше коммисия, тем быстрее пройдет перевод fee = 10000 # Генерация транзакции tx_hash = my_key.create_transaction([(data[5], sum, 'btc')], fee=fee, absolute_fee=True) print(tx_hash) url = 'https://blockchain.info/pushtx' x = requests.post(url, data={'tx': tx_hash}) result = x.text sql = "UPDATE users SET state = {} WHERE chatid = {}".format(0, message.chat.id) cursor.execute(sql) conn.commit() await bot.send_message(message.chat.id, result) except Exception: await bot.send_message(message.chat.id, "⚠ Ошибка при выолнении транзакции") else: await bot.send_message(message.chat.id, '⚠️ На вашем балансе недостаточно средств.') except ValueError: await bot.send_message(message.chat.id, '⚠️Неправильно введена сумма отправления, попробуйте еще раз') Исходники и как запустить Скачать исходники бота можно тут github.com/Lil-hack/blockchain-client Склонировав репозиторий, устанавливаем необходимые пакеты:pip install -r requirements.txtНекоторые библиотеки у меня не заработали на windows, так что лучше сразу запускать на linux. В файле main.py заменяем ваш токен телеграм бота: # Ваш токен от BotFather
TOKEN = 'YOUR TOKEN' # Ваша seed фраза
seed = 'YOUR SEED' =========== Источник: habr.com =========== Похожие новости:
Криптография ), #_python, #_sqlite, #_github, #_kriptovaljuty ( Криптовалюты ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:23
Часовой пояс: UTC + 5