こんにちは、はやたす(@hayatasuuu )です。
この記事ではSolana BlockchainでPythonを使ってSOLを送金する方法を書いていきます。
基本的にはEthereumの思想を受け継いでるので、Web3をインスパイアしたライブラリを使うことになります。
使用するOSとPythonのバージョンは以下のとおりです。
$ python -V
# Python 3.9.7
$ cat /etc/os-release
# PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
# NAME="Debian GNU/Linux"
# VERSION_ID="11"
# VERSION="11 (bullseye)"
# VERSION_CODENAME=bullseye
また記事内ではスクリプトを準備してるような書き方ですが、手元で実行するときはJupyterを使っています。
Botを組むわけではないので、セルごとに実行できるJupyter環境が良いと思います。
目次
Solana BlockchainでPythonを使ってSOLを送金する方法
Solana BlockchainでPythonを使ってSOLを送金するには、以下のステップが必要になります。
- ライブラリをインストールする
- キーペア(アカウント)を作成する
- 送信者から受信者への送金トランザクションを作成する
順番に解説していきます。
STEP1 : ライブラリをインストールする
まずはライブラリをインストールします。
Solana版のWeb3をPythonで使うためのライブラリ名も”solana”です。
pipコマンドでインストールしましょう。
$ pip install solana
インストールが完了したら、試しにdevnetでHealth Checkしてみます。
以下を実行してみてください。
from solana.rpc.api import Client
client = Client("https://api.devnet.solana.com")
print('Health Check:', client.is_connected())
True
が返ってくれば大丈夫です。
clientっていう
fromとかimportって何?
fromで別のフォルダ(ライブラリ)に書いてある関数を実行できるようになる。from〇〇importXXをすることで、いちいち〇〇のふぉるだの~XXって書く必要がなくなり、XXだけで関数を実行できるようになる。
https://techacademy.jp/magazine/23097
STEP2 : キーペア(アカウント)を作成する
次にキーペアを作成します。
以下では32バイトのseedを元に「送信者用のキーペア」を作成しています。
from solana.keypair import Keypair
sender = Keypair.from_seed(Keypair().seed)
sender_pubkey = sender.public_key
sender_prikey = sender.secret_key
print("=" * 10, "Public Key", "=" * 10)
print(sender_pubkey)
print("=" * 10, "Private Key", "=" * 10)
print(sender_prikey.hex())
厳密にいうとキーペアの作成は、3行目のハイライト部分で完了しています。
Public Keyは文字列で表示されますが、
Private Keyに関してはバイトで出力されるのでhex()
を使って文字列に戻しています。
Private Keyも出力しましたが、
送金で使うのはsender
とsender_pubkey
だけです。
念の為アカウント情報を確認してみます。
print(client.get_account_info(sender_pubkey))
# {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937162}, 'value': None}, 'id': 1}
まだ残高がないのでvalue
はNone
です。
続いて受信者のアカウントも同じ手順で作成しましょう。
receiver = Keypair.from_seed(Keypair().seed)
receiver_pubkey = receiver.public_key
receiver_prikey = receiver.secret_key
print("=" * 10, "Public Key", "=" * 10)
print(receiver_pubkey)
print("=" * 10, "Private Key", "=" * 10)
print(receiver_prikey.hex())
もちろん残高を確認してもゼロになっています。
print(client.get_account_info(receiver_pubkey))
# {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937220}, 'value': None}, 'id': 2}
なんでIDが2になるんだろう?
これでキーペアの作成が完了しました。
STEP3 : 送信者から受信者への送金トランザクションを作成する
二人とも残高がゼロでは、面白くありません。そもそも送金できません。
というわけで送信者用のウォレットにSOLを補給しましょう。
以下のスクリプトで送信者アカウントに100,000lamports送金できます。
r = client.request_airdrop(sender_pubkey, 100000)
print(r)
# {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937554}, 'value': 99954}, 'id': 5}
lamportsは、ETHでいうとGWeiに相当します。
つまり1SOL=10億lamportsです。
- 1lamports = 0.000000001SOL
- 1SOL = 10億lamports
ゆえに今回受け取る100,000lamportsは0.001SOLになります。
lambdaとはなにか。lambdaで無名の関数を定義できる。
下記のdefとlambdaは同じもの。
def add_def(a, b=1):
return a + b
add_lambda = lambda a, b=1: a + b
print(add_def(3, 4))
# 7
print(add_def(3))
# 4
print(add_lambda(3, 4))
# 7
print(add_lambda(3))
# 4
10**8とは? 10の8乗。
lamp2sol = lambda lamp: lamp/10**8
sol2lamp = lambda sol: sol*(10**8)
print(lamp2sol(100000))
# 0.001
引数では100,000を指定しましたが、実際には99,954だけ送られてきます。
46だけ没収されていますね。
そういえば僕が好きな白石麻衣さんも乃木坂46から没収されました…。
さて。トークンの準備が完了したら、いよいよトランザクションを作成します。
まずは送信者と受信者のバランス(残高)を確認しておきます。
print(client.get_balance(sender_pubkey))
print(client.get_balance(receiver_pubkey))
# {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937600}, 'value': 99954}, 'id': 6}
# {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937600}, 'value': 0}, 'id': 7}
次に送信者から受信者に送金するトランザクションを作成です。
今回は試しに1,000lamportsだけ送金してみました。
あとで書きますが、手数料で5,000lamportsほど消費します。
そのことを踏まえた上で、送金するlamportsの量を選んでみてください。
from solana.system_program import TransferParams, transfer
from solana.transaction import Transaction
# トランザクションの作成
tx = Transaction()
tx_params = TransferParams(
from_pubkey=sender_pubkey,
to_pubkey=receiver_pubkey,
lamports=1000
)
tx.add(transfer(tx_params))
client.send_transaction(tx, sender)
# {'jsonrpc': '2.0', 'result': '(中略)', 'id': 9}
最後に無事送金できたか確認してみましょう。
以下を実行してReceiver側の残高が増えていれば送金に成功しています。
print('Sender:', client.get_balance(sender_pubkey))
print('Receiver:', client.get_balance(receiver_pubkey))
# Sender: {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937704}, 'value': 93954}, 'id': 10}
# Receiver: {'jsonrpc': '2.0', 'result': {'context': {'slot': 87937706}, 'value': 954}, 'id': 11}
またこのとき、送信者へのlamports送金と同じで、46だけ減った状態で受け取っています。
- 送金したlamports : 1,000
- 受け取ったlamports : 954
- 差分 : 46
送信者側は、送金前が99,954だったので6,000lamports減っていることが分かります。
今回は1,000lamports送金していたので、手数料で5,000lamportsかかっていることが分かりますね。
5,000という数字だけ見ると割高に感じますが、5,000lamports = 0.00005SOLです。
この記事を書いている時点で1SOL = 18,000円くらいなので、今回の送金でかかった手数料は0.9円になります。
Ethereumでは考えられない手数料ですね。
なお、送金する前に必要になるであろう手数料を確認することもできます。
print(client.get_fees())
# {'jsonrpc': '2.0',
# 'result': {'context': {'slot': 87937778},
# 'value': {'blockhash': '(中略)',
# 'feeCalculator': {'lamportsPerSignature': 5000},
# 'lastValidBlockHeight': 85993666,
# 'lastValidSlot': 87938078}},
# 'id': 14}
ハイライトした部分を確認すれば、必要になるであろう手数料が書かれていますね。