見出し画像

最新SymbolSDKを使って複数人に個別枚数を一斉送信するプログラムを実装してみた(Python)

2022年10月にアグリゲートトランザクションの脆弱性を回避するためのハードフォークが実施され、過去に使用できていたSDKが使えなくなりました。
過去の記事はコチラ:https://nemlog.nem.social/blog/68032

開発環境の構築

SDKのインストールはターミナルにて以下のコードを打つことで実現できます。

pip install symbol-sdk-python

pip listコマンドを使って、symbol-sdk-pythonのバージョンが3.0.3になっていることをご確認ください。

新SDKを使ったPythonによる一斉送信プログラム

コード全文を公開します(サッと作ったので乱雑ですが、勘弁してください)
※本コードはメインネットで動作する様に作成しています

from binascii import unhexlify
from symbolchain.CryptoTypes import PrivateKey
from symbolchain.symbol.KeyPair import KeyPair
from symbolchain.facade.SymbolFacade import SymbolFacade

import datetime
import http.client
from binascii import hexlify

# トランザクション送信に使う手数料
fee_size = 0.4

# 一斉送信用メッセージ
msg = "******ここに一斉送信時に入力したいメッセージを記載します******"

# 宛先リスト(ここを自由に書き換えてください[配列の作り方は過去記事参照])
toList = [
    [SymbolFacade.Address("******送信先アドレスを入力******"),1], # 「1」の部分が送信するXYMの枚数
    [SymbolFacade.Address("******送信先アドレスを入力******"),1],
]

# メインネットのSymbol mosaicID
MOSAIC = 0x6BED913FA20223F8

def add_embedded_transfers(facade, public_key, toList):

    embedded_transactions = []

    for to in toList:
        address = to[0]
        mosaic_size = to[1]
        embedded_transaction = facade.transaction_factory.create_embedded({
            'type': 'transfer_transaction',
            'signer_public_key': public_key,
            'recipient_address': address,
            'mosaics': [
                {'mosaic_id': MOSAIC,'amount': int(mosaic_size * 1000000)}
            ],
            'message': bytes(1) + msg.encode('utf8')
        })

        embedded_transactions.append(embedded_transaction)

    return embedded_transactions


def main():
    facade = SymbolFacade('mainnet')

    Prikey = PrivateKey(unhexlify("******ここにご自身の送信元のプライベートキーを入力******"))
    Keypair = KeyPair(Prikey)
    Pubkey = Keypair.public_key
    Address = facade.network.public_key_to_address(Pubkey)
    print(Address)

    embedded_transactions = add_embedded_transfers(facade, Pubkey, toList)
    merkle_hash = facade.hash_embedded_transactions(embedded_transactions)
    deadline = (int((datetime.datetime.today() + datetime.timedelta(hours=2)).timestamp()) - 1615853185) * 1000

    aggregate_transaction = facade.transaction_factory.create({
        'type': 'aggregate_complete_transaction',
        'signer_public_key': Pubkey,
        'fee': int(fee_size * 1000000),
        'deadline': deadline,
        'transactions_hash': merkle_hash,
        'transactions': embedded_transactions
    })

    aggregate_transaction.version = 2

    signature = facade.sign_transaction(Keypair, aggregate_transaction)
    facade.transaction_factory.attach_signature(aggregate_transaction, signature)

    print(f'Hash: {facade.hash_transaction(aggregate_transaction)}\n')
    print(aggregate_transaction)

    payload = {"payload": hexlify(aggregate_transaction.serialize()).decode('utf8').upper()}

    import json
    json = json.dumps(payload)

    headers = {'Content-type': 'application/json'}

    conn = http.client.HTTPConnection("xym695.allnodes.me",3000)
    conn.request("PUT", "/transactions", json,headers)

    response = conn.getresponse()
    print(response.status, response.reason)

if __name__ == '__main__':
	main()

今回変更があったのは、大きくはトランザクションのtypeでしょうか?
あと、地味にモザイクの配列内の書き方が変わってたような気がするのですが…(まさかここで詰まるとは思いませんでした笑)
transaction_factory.createの後、バージョン2を指定するところがミソですね。

後半のネットワークへのアナウンス部分は変更がなさそうです。
アグリゲートトランザクションの修正なので、当たり前といえば当たり前ですね!

テストネットで動作させたい場合

テストネットで動作させたい場合は、上記のコードの内、以下を変更する必要があります。

テストネットのモザイクIDに変更する

# テストネットのmosaicID
MOSAIC = 0x3A8416DB2D53B6C8

テストネットであることを記述する

facade = SymbolFacade('testnet')

トランザクションの有効期限を変更する

deadline = (int((datetime.datetime.today() + datetime.timedelta(hours=2)).timestamp()) - 1637848847) * 1000

最後に

実際に環境構築してみて上手くいかない…という場合は、Twitterの(@kotopapa8)までDMください。

当方、TwitterをメインにSymbol関連の活動を行っております。
イベント・開発(自己満)・ノード運営(xym695.allnodes.me/xym815.allnodes.me)・Symbol決済店舗まとめサイトの運営などを行っていますので、本記事がタメになった!という方は、投げXYM(NARXOM3ILDL25GNMO6WTGMPYAHHGWOIOXYIVDBY)や委任を頂けると嬉しいです。


この記事が気に入ったらサポートをしてみませんか?