이번 튜토리얼에서는 Python을 사용해 NeoX 블록체인에서 토큰을 전송하는 방법을 하나씩 따라가며 배워봅니다.
블록체인과 스마트 컨트랙트에 익숙하지 않은 분들도 이해할 수 있도록, 각 단계마다 어떤 의미가 있는지 친절히 설명드릴게요.
예시에서는 100 $NDMEME 토큰을 내 지갑에서 다른 지갑으로 전송하는 실제 코드를 작성해보며, NeoX 체인과 어떻게 상호작용하는지도 함께 익혀봅니다.
토큰을 전송하려면 몇 가지 준비물이 필요합니다. 마치 은행 송금 전에 계좌번호, 비밀번호, 오픈뱅킹 API가 필요한 것과 비슷해요.
👉 Metamask 설정
가이드를 참고해 지갑을 설치한 뒤, 아래처럼 개인키를 확인할 수 있습니다:
Metamask에서 개인키 내보내기
지갑 우측 상단 점 세 개 > "Account details"

"Export Private Key" 클릭

비밀번호 입력 후 개인키 복사
⚠️ 주의: 개인키는 절대 다른 사람과 공유하면 안 됩니다. 누구든 이 키만 있으면 당신의 자산을 가져갈 수 있어요.
이제 본격적으로 코드를 작성해볼게요.Python을 이용해 NeoX 체인과 대화하려면 먼저 web3.py라는 도구를 설치해야 해요. 이 도구는 블록체인과 연결하고, 트랜잭션을 만들고, 전송하는 모든 작업을 도와줍니다.
pip install web3 python-dotenv
web3는 블록체인과 연결해주는 도구이고, dotenv는 내 민감 정보를 코드 바깥의 .env 파일로 따로 보관할 수 있게 해줘요.
from web3 import Web3
from web3.middleware import geth_poa_middleware
from eth_account import Account
from dotenv import load_dotenv
import os
NeoX는 POA(Proof of Authority) 방식으로 작동해서 geth_poa_middleware를 꼭 주입해줘야 합니다. 이 설정을 하지 않으면 연결이 되지 않을 수 있어요.
개인키를 코드에 직접 쓰지 않고 .env라는 파일에 따로 적어두면 훨씬 안전합니다.
# .env 파일 예시
PRIVATE_KEY=0x123...
load_dotenv()
PRIVATE_KEY = os.getenv("PRIVATE_KEY")
이렇게 하면 코드가 깔끔해지고 실수로 GitHub 등에 업로드했을 때도 덜 위험하죠.
ACCOUNT_ADDRESS = "내 지갑 주소"
SAMPLE_ADDRESS = "받는 사람 주소"
TOKEN_CONTRACT = "0xE816deE05cf6D0F2a57EB4C489241D8326B5d106"
RPC = "https://mainnet-1.rpc.banelabs.org/"
NDMEME_ABI = open("ndmeme_abi.json").read()
이 값들은 우리가 사용할 계정, 목적지 주소, 토큰 정보, RPC 연결 주소를 저장해둔 거예요. 이걸 기반으로 트랜잭션을 만들게 됩니다.
w3 = Web3(Web3.HTTPProvider(RPC))
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
이제 NeoX 체인에 연결하는 Web3 객체를 만들었습니다. 이 객체를 통해 앞으로 모든 작업이 이뤄질 거예요.
스마트컨트랙트와 대화하려면, 그 컨트랙트의 사용 설명서가 필요해요. 이걸 ABI라고 부릅니다.
[
{
"constant": false,
"inputs": [
{ "name": "_to", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "transfer",
"outputs": [{ "name": "", "type": "bool" }],
"type": "function"
}
]
이건 "누구에게 얼마를 전송한다"는 transfer 함수의 구조예요.
with open(ABI_PATH) as f:
abi = f.read()
token = w3.eth.contract(address=Web3.to_checksum_address(TOKEN_CONTRACT), abi=abi)
이렇게 하면 이제부터 Python 코드로 이 토큰 컨트랙트를 조작할 수 있게 됩니다.
nonce = w3.eth.get_transaction_count(ACCOUNT_ADDRESS)
tx = token.functions.transfer(
Web3.to_checksum_address(SAMPLE_ADDRESS), w3.to_wei(100, 'ether')
).build_transaction({
'chainId': w3.eth.chain_id,
'gas': 100000,
'gasPrice': w3.eth.gas_price,
'nonce': nonce
})
signed_tx = w3.eth.account.sign_transaction(tx, private_key=PRIVATE_KEY)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
print(f"트랜잭션 전송 완료: {w3.to_hex(tx_hash)}")
여기서는 트랜잭션을 하나 만들어서, 지갑의 비밀키로 서명하고, 네트워크에 전송까지 하는 과정을 담고 있어요.
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt["status"] == 1:
print("트랜잭션 성공!")
else:
print("트랜잭션 실패.")
전송한 트랜잭션이 블록에 잘 포함되었는지 확인하는 과정이에요. 실패했을 경우 이유를 살펴보며 수정할 수 있어요.
import json
import os
from web3 import Web3
from web3.middleware import geth_poa_middleware
from eth_account import Account
from dotenv import load_dotenv
# 1. 환경변수 불러오기 (.env 파일에 PRIVATE_KEY 설정되어 있어야 함)
load_dotenv()
PRIVATE_KEY = os.getenv("PRIVATE_KEY")
# 2. 주요 정보 설정
ACCOUNT_ADDRESS = "0x내지갑주소" # 내 지갑 주소
RECEIVER_ADDRESS = "0x받는사람주소" # 받는 사람 주소
TOKEN_CONTRACT = "0xE816deE05cf6D0F2a57EB4C489241D8326B5d106" # 토큰 컨트랙트 주소
RPC = "https://rpc-testnet.neox.network" # NeoX 테스트넷 RPC
ABI_PATH = "./bdmint-abi.json" # 토큰 ABI 파일 경로
# 3. NeoX 체인 연결
w3 = Web3(Web3.HTTPProvider(RPC))
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
# 4. 토큰 ABI 로드 및 컨트랙트 인스턴스 생성
with open(ABI_PATH, "r") as f:
abi = json.load(f)
token = w3.eth.contract(
address=Web3.to_checksum_address(TOKEN_CONTRACT),
abi=abi
)
# 5. nonce 가져오기 (내 계정에서 지금까지 몇 개의 트랜잭션을 보냈는지)
nonce = w3.eth.get_transaction_count(ACCOUNT_ADDRESS)
# 6. 토큰 전송 트랜잭션 구성
tx = token.functions.transfer(
Web3.to_checksum_address(RECEIVER_ADDRESS),
w3.to_wei(100, 'ether') # 100 BDMINT (소수점 없는 토큰이면 그대로 100)
).build_transaction({
'chainId': w3.eth.chain_id,
'gas': 100000,
'gasPrice': w3.eth.gas_price,
'nonce': nonce
})
# 7. 트랜잭션 서명
signed_tx = w3.eth.account.sign_transaction(tx, private_key=PRIVATE_KEY)
# 8. 트랜잭션 전송
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
print(f"트랜잭션 전송 완료! 해시: {w3.to_hex(tx_hash)}")
# 9. 트랜잭션 성공 여부 확인
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt["status"] == 1:
print("✅ 트랜잭션 성공!")
else:
print("❌ 트랜잭션 실패.")
여기까지 잘 따라오셨나요? 이제 Python을 통해 NeoX에서 토큰을 전송하는 전체 흐름을 직접 구현해볼 수 있게 되었어요.앞으로는 이 경험을 바탕으로 자동화 도구나 dApp도 만들 수 있을 거예요.