Bitcoin SV w Pythonie
W poprzednich wpisach (1, 2) wygenerowaliśmy klucz prywatny, poznaliśmy adres
testnet, mainnet, sprawdziliśmy saldo i
pobraliśmy niewydane transakcje. Teraz nauczymy
się, jak przy pomocy oficjalnego bsv-sdk dla Pythona zbudować prostą
transakcję, którą wyślemy na swój własny adres testnetowy. Jak to w ogóle możliwe, że możesz wysłać Bitcoina… samemu sobie?
W Bitcoinie nikt nie wie, kim jesteś - sieć tylko sprawdza, czy umiesz wydać monety zgodnie z zasadami a skoro umiesz, to możesz je wysłać.. nawet z powrotem do siebie i sieci jest to kompletnie obojętne :)

UTXO: Bitcoin SV
W tradycyjnym banku masz konto i tutaj wszystko ląduje do jednego wora:

- ma konkretną kwotę,
- ma "kłódkę" - skrypt, który mówi: kto i na jakich warunkach może je wydać.
Twoje "saldo" to tak naprawdę zbiór wszystkich wierszy, a każdy z tych wierszy potrafisz otworzyć swoim kluczem prywatnym.

I teraz chcesz wydać 50zł w sklepie. Musisz wydać/zużyć jeden z wierszy (wydajemy 100zł), a Twoja reszta (50zł) wracając, utworzy nowy wiersz.

Proste? :) No to przechodzimy do kodu.
Tworzenie i Rozgłaszanie Transakcji BSV
Krok 0: Ile będziemy wysyłać :)
do_wyslania = 222
Krok 1: Zadeklaruj funkcję asynchroniczną
async def create_and_broadcast_transaction():Na początek zadeklaruj asynchroniczną funkcję o nazwie create_and_broadcast_transaction. Słowo kluczowe async jest ważne - dzięki niemu będziesz mógł czekać na odpowiedzi z sieci bez zawieszania całego programu.
Krok 2: Załaduj poprzednią transakcję
Poprzedni wpis, zakończyliśmy wypisaniem niewydanej transakcji w hex (tx_hex); musisz ją teraz przekazać:Krok 3: Przygotuj input - określ źródło pieniędzy
- Stwórz nowy obiekt TransactionInput.
- Przypisz poprzednią transakcję (source_tx) jako źródło. Ten parametr mówi: "pieniądze biorę z tej transakcji"
- Wyciągnij i przypisz ID źródłowej transakcji. source_tx.txid() to metoda, która generuje unikalny identyfikator tej transakcji. ID jednoznacznie identyfikuje transakcję na blockchainie - bez niego sieć nie wiedziałaby, którą transakcję masz na myśli.
- Określ, który output ze źródłowej transakcji chcesz wydać. 0 oznacza pierwszy output (liczymy od zera). Transakcja może mieć wiele wyjść, ale Ty bierzesz tylko jedno - pierwsze.
- Przygotuj szablon skryptu odblokowania. .unlock(klucz_prywatny) - generuje skrypt, który będzie podpisany Twoim kluczem prywatnym Ten skrypt będzie dowodem, że jesteś właścicielem tych pieniędzy i masz prawo je wydać.
source_txid=source_tx.txid(), # (3)
unlocking_script_template=P2PKH().unlock(klucz_prywatny),) # (5)
Zamknij konfigurację input-u.
Krok 4: Przygotuj output - określ cel pieniędzy
- Stwórz nowy obiekt TransactionOutput - to będzie wyjście Twojej transakcji :)
- Stwórz skrypt blokujący pieniądze - to blokuje satoshi na Twoim adresie testnet. Ten fragment .lock(address_testnet) wpisujemy zmienną naszego adresu lub możesz wpisać swój adres jako string .lock("xxxxxxxxxxx")
- Określ ilość satoshi w tym outputcie."satoshis" to zmienna przechowująca konkretną liczbę (np. 222 - u nas to zmienna do_wyslania)
- Oznacz ten output jako zmianę (resztę). Jeśli ustawisz change=True - biblioteka automatycznie wyśle resztę pieniędzy (różnicę między inputem a outputem) z powrotem na Twój adres. Jeśli ustawisz change=False - reszta pieniędzy zostanie zmarnowana.
tx_output = TransactionOutput( # (1)
locking_script=P2PKH().lock(address_testnet), # (2)
satoshis=do_wyslania, # (3)
change=True) # (4)
Zamknij konfigurację output-u. Teraz output jest gotowy.
Krok 5: Połącz input i output w transakcję
tx = Transaction([tx_input], [tx_output], version=1)
- [tx_input] - lista inputów (tutaj jeden, w nawiasach kwadratowych)
- [tx_output] - lista outputów (tutaj jeden)
- version=1 - określa wersję transakcji (1 to oryginalna wersja)
Krok 6: Wyświetl informacje
Wydrukuj na ekran informacyjny komunikat.print(f"{address_testnet} wysyła {do_wyslania} satoshi")
Krok 7: Oblicz opłatę i podpisz transakcję
Oblicz i ustaw automatyczną opłatę. Metoda fee() analizuje rozmiar transakcji (w bajtach) i wylicza odpowiednią opłatę sieciową. Opłata automatycznie zostanie odliczona z outputu. Podpisz całą transakcję Twoim kluczem prywatnym.
Krok 9: Przygotuj klucz API
api_key = 'testnet_73657152612......'Zadeklaruj swój klucz API w zmiennej. Ten klucz identyfikuje Cię wobec usługi Taal ARC i pozwala na rozgłaszanie transakcji.
Krok 10: Rozgłoś transakcję do sieci
Wyślij podpisaną transakcję do sieci Bitcoin SV
- tx.broadcast() - wysyła transakcję
- ARC(...) - tworzy klienta ARC z endpointem serwera i Twoim kluczem API
- await - czeka na odpowiedź z serwera
- response - przechowuje odpowiedź - informacje o tym, czy rozgłoszenie się powiodło
Krok 11: Wyświetl status rozgłoszenia
Wydrukuj status odpowiedzi serwera.
Krok 12: Wyświetl ID transakcji
Wydrukuj unikalny identyfikator Twojej nowej transakcji, którą będziesz mógł zobaczyć w blockchain --> https://test.whatsonchain.com/Krok 13: Uruchom funkcję
if __name__ == "__main__":asyncio.run(create_and_broadcast_transaction())
Kosmetyka:
Wypisz numer indeksu:
Zmodyfikuj zmienną source_output:
source_output_index=tx_pos,
Pełny kod:
nest_asyncio.apply()
import asyncio
from bsv import PrivateKey, P2PKH, ARC, Transaction, TransactionInput, TransactionOutput
import requests
import json
moj_klucz = "KwVs88aLx6ZuZmphr........................."
klucz_prywatny = PrivateKey(moj_klucz)
address_testnet = klucz_prywatny.address(network = "testnet")
url = f"https://api.whatsonchain.com/v1/bsv/test/address/{address_testnet}/confirmed/balance"
response = requests.get(url)
data = response.json()
saldo = data['confirmed']
print(f"Adres testnet : {address_testnet}")
print(f"Saldo : {saldo} satoshi / {saldo / 100000000} BSV")
url = f"https://api.whatsonchain.com/v1/bsv/test/address/{address_testnet}/unspent/all"
response = requests.get(url)
data = response.json()
txid = data['result'][0]['tx_hash']
tx_pos = data['result'][0]['tx_pos']
print(f"\nTransakcja z niewydanym UTXO: {txid}")
print(f"Indeks transakcji: {tx_pos}\n")
url = f"https://api.whatsonchain.com/v1/bsv/test/tx/{txid}/hex"
response = requests.get(url)
tx_hex = response.text
print(f"HEX : {tx_hex}\n")
do_wyslania = 333
input("Naciśnij Enter by kontynuować..")
async def create_and_broadcast_transaction():
source_tx = Transaction.from_hex(tx_hex)
tx_input = TransactionInput(
source_transaction=source_tx,
source_txid=source_tx.txid(),
source_output_index=tx_pos,
unlocking_script_template=P2PKH().unlock(klucz_prywatny),
)
tx_output = TransactionOutput(
locking_script=P2PKH().lock(address_testnet),
satoshis=do_wyslania,
change=True
)
tx = Transaction([tx_input], [tx_output], version=1)
print(f"{address_testnet} wysyła {do_wyslania} satoshi")
tx.fee()
tx.sign()
api_key = 'testnet_2d8a5a0745..........'
response = await tx.broadcast(ARC('https://api.taal.com/arc', api_key))
print(f"Status rozgłoszenia: {response.status}")
print(f"ID transakcji: {tx.txid()}")
if __name__ == "__main__":
asyncio.run(create_and_broadcast_transaction())
input("Koniec")
- wygenerowany klucz prywatny,
- uzupełnione saldo za pomocą kranu testnet,
- sprawdzone saldo z poziomu kodu (a nie poprzez explorer bloków na stronie www),
- ustalone niewydane UTXO
- pobrany hex z powyższego UTXO
- ustalony indeks z UTXO
- zbudowaną funkcję do zbudowania wejść i wyjść
- rozgłoszenie transakcji
- pobranie hasha transakcji
Wysłaliśmy sami sobie Bitcoin'a :)
Co dalej?
W kolejnym wpisie, dalej będziemy pracować na dotychczasowym kodzie. Zbudujemy transakcję w której wyślemy środki na jakiś inny adres a reszta będzie wracała na nasz adres. Pokażę też, dwie metody na zbudowanie takiej transakcji :) Jeśli masz jakieś pytania, nie zawahaj się ich zadać w komentarzach.
Cześć!
**Gwarantuję Ci niezmienność moich treści**
Hash artykułu:
ID transakcji: sprawdź OP_RETURN i porównaj jego hash
Komentarze
Prześlij komentarz