Published on

[NeoX Tutorial] Batch sending tokens on NeoX with Python

Authors

Description

On this article we will see how to batch send token on NeoX blockchain in Python.

As an example we will make a simple script allowing us to send 1000 $NDMEME token to 5 different wallets in the same transaction.

Getting parameters value

For doing this we will use the multiTransfers of FTWHelpers contract.

If you followed this previous article you will already know how to retrieve most of the required parameters. The only new things we will need ar the FTWHelpers hash (0xDfa53F8deA15CE39A23D57874e03eE0E76425e01) and ABI that can be found here.

Python code

Now we have all the information we need and we can switch to the coding step.

Let's start by installing the web3 Python module we will use for interacting with NeoX using the command pip install web3 and then make the script.

The code will contains the following parts. The import of the web3 Python module:

from web3 import Web3
from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3.middleware import ExtraDataToPOAMiddleware

Then the definition of the variable we retrieved previously and we will use for our call:

PK = os.environ.get('NEOX_PK') #Our wallet private key
FTW_HELPERS_HASH = "0xDfa53F8deA15CE39A23D57874e03eE0E76425e01"
FTW_HELPERS_ABI = open("ftw_helpers_abi.json").read() #The ABI file for FTWHelpers contract
NDMEME_HASH = "0xE816deE05cf6D0F2a57EB4C489241D8326B5d106"
NDMEME_ABI = open("ndmeme_abi.json").read() #The ABI file for NDMEME contract
NDMEME_AMOUNT = 1000000000000000000000
RECEIVERS = [
    "0x32e35665B4bb970c2b9348a6B2b2517D57D8701A",
    "0xfE2a5462b3f04c466b7554176050501828aE1103",
    "0xdeadc0de9FE6eC6B0B083d617B827F86e4D1EE14",
    "0xB5b184b4A5304BE50E45F9489dF9Bce1cfc40F90",
    "0x1241f44BFA102ab7386C784959BAe3D0fB923734"
]
RPC_ENDPOINT = "https://mainnet-1.rpc.banelabs.org/"

Now we can instantiate a Web3 object that will help connecting to NeoX chain:

w3 = Web3(Web3.HTTPProvider(RPC_ENDPOINT))
account: LocalAccount = Account.from_key(PK)
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)

We will then need to build a first transaction to allow FTWHelpers contract to spend 5000 $NDMEME to send those to the 5 wallets:

nonce = w3.eth.get_transaction_count(account.address)
contract = w3.eth.contract(NDMEME_HASH, abi=NDMEME_ABI)
tx = contract.functions.increaseAllowance(FTW_HELPERS_HASH, len(RECEIVERS) * NDMEME_AMOUNT).build_transaction({
    'from': account.address,
    'nonce': nonce
})
signed_tx = w3.eth.account.sign_transaction(tx, PK)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
tx_result = w3.eth.wait_for_transaction_receipt(tx_hash.hex())
print(f"Result for increaseAllowance transaction: {tx_result}")

Now we will format the inputs for our transfer transaction:

tokens = [NDMEME_HASH] * len(RECEIVERS)
amounts = [NDMEME_AMOUNT] * len(RECEIVERS)
tokens = [Web3.to_checksum_address(x) for x in tokens]
receivers = [Web3.to_checksum_address(x) for x in RECEIVERS]

And we can build the transaction sending 1000 $NDMEME to our 5 wallets:

nonce = w3.eth.get_transaction_count(account.address)
contract = w3.eth.contract(FTW_HELPERS_HASH, abi=FTW_HELPERS_ABI)
tx = contract.functions.multiTransfers(tokens, receivers, amounts).build_transaction({
    'from': account.address,
    'nonce': nonce
})
signed_tx = w3.eth.account.sign_transaction(tx, PK)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
tx_result = w3.eth.wait_for_transaction_receipt(tx_hash.hex())
print(f"Result for transfer transaction: {tx_result}")

Putting everything together we have the following final script.

import os

from web3 import Web3
from eth_account import Account
from eth_account.signers.local import LocalAccount
from web3.middleware import ExtraDataToPOAMiddleware


PK = os.environ.get('NEOX_PK') #Our wallet private key
FTW_HELPERS_HASH = "0xDfa53F8deA15CE39A23D57874e03eE0E76425e01"
FTW_HELPERS_ABI = open("ftw_helpers_abi.json").read() #The ABI file for FTWHelpers contract
NDMEME_HASH = "0xE816deE05cf6D0F2a57EB4C489241D8326B5d106"
NDMEME_ABI = open("ndmeme_abi.json").read() #The ABI file for NDMEME contract
NDMEME_AMOUNT = 1000000000000000000000
RECEIVERS = [
    "0x32e35665B4bb970c2b9348a6B2b2517D57D8701A",
    "0xfE2a5462b3f04c466b7554176050501828aE1103",
    "0xdeadc0de9FE6eC6B0B083d617B827F86e4D1EE14",
    "0xB5b184b4A5304BE50E45F9489dF9Bce1cfc40F90",
    "0x1241f44BFA102ab7386C784959BAe3D0fB923734"
]
RPC_ENDPOINT = "https://mainnet-1.rpc.banelabs.org/"

w3 = Web3(Web3.HTTPProvider(RPC_ENDPOINT))
account: LocalAccount = Account.from_key(PK)
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)

print(f"Your hot wallet address is {account.address}")

nonce = w3.eth.get_transaction_count(account.address)
contract = w3.eth.contract(NDMEME_HASH, abi=NDMEME_ABI)
tx = contract.functions.increaseAllowance(FTW_HELPERS_HASH, len(RECEIVERS) * NDMEME_AMOUNT).build_transaction({
    'from': account.address,
    'nonce': nonce
})
signed_tx = w3.eth.account.sign_transaction(tx, PK)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
tx_result = w3.eth.wait_for_transaction_receipt(tx_hash.hex())
print(f"Result for increaseAllowance transaction: {tx_result}")

tokens = [NDMEME_HASH] * len(RECEIVERS)
amounts = [NDMEME_AMOUNT] * len(RECEIVERS)
tokens = [Web3.to_checksum_address(x) for x in tokens]
receivers = [Web3.to_checksum_address(x) for x in RECEIVERS]

nonce = w3.eth.get_transaction_count(account.address)
contract = w3.eth.contract(FTW_HELPERS_HASH, abi=FTW_HELPERS_ABI)
tx = contract.functions.multiTransfers(tokens, receivers, amounts).build_transaction({
    'from': account.address,
    'nonce': nonce
})
signed_tx = w3.eth.account.sign_transaction(tx, PK)
tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
tx_result = w3.eth.wait_for_transaction_receipt(tx_hash.hex())
print(f"Result for transfer transaction: {tx_result}")

Conclusion

You now have an example of Python script to batch send tokens on NeoX blockchain. Feel free to modify It to your own need and to reach me on Discord if you need more help.