Python scripts
Python functions and below Etherdoek's ABI.
Functions for creating the canvas from the blockchain and for buying and chaning pixels.
Hex values can be entered as a string in the buy and change functions. For example '000000', 'FFFFFF', 'E02619'.
import web3
import json
import pandas as pd
import numpy as np
import datetime as dt
from PIL import Image
INFURA_KEY = 'insert key here'
FROM_BLOCK = 9_825_620
ADDRESS_ETHERDOEK = '0x67B4Ef189A68133aB3a726b85d289B912C23e0B0'
w3 = web3.Web3(web3.HTTPProvider('https://mainnet.infura.io/v3/' + INFURA_KEY))
w3_events = web3.Web3(web3.WebsocketProvider('wss://mainnet.infura.io/ws/v3/' + INFURA_KEY))
gas_price = '5' # Check https://ethgasstation.info
chain_id = 1
with open('abi_etherdoek.json') as json_file: # ABI can be found at https://www.etherdoek.com/python_scripts
abi_etherdoek = json.load(json_file)
contract_etherdoek = w3.eth.contract(address=ADDRESS_ETHERDOEK, abi=abi_etherdoek)
contract_etherdoek_events = w3_events.eth.contract(address=ADDRESS_ETHERDOEK, abi=abi_etherdoek)
def etherdoek_buy_pixel(wallet_address, wallet_private_key, location, hex_value, pixel_price=5_000_000_000_000_000):
nonce = w3.eth.getTransactionCount(wallet_address)
txn_dict = contract_etherdoek.functions.buy_pixel(location,
hex_value).buildTransaction({'gasPrice': w3.toWei(gas_price, 'gwei'),
'nonce': nonce,
'value': pixel_price,
'chainId': chain_id,
'gas': 500_000})
signed_txn = w3.eth.account.signTransaction(txn_dict, wallet_private_key)
txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
txn_receipt = None
count = 0
while txn_receipt is None:
try:
txn_receipt = w3.eth.getTransactionReceipt(txn_hash)
except:
time.sleep(1)
if txn_receipt is None:
return {'status': 'failed', 'error': 'timeout'}
else:
return {'status': 'added', 'txn_receipt': txn_receipt}
def etherdoek_change_pixel(wallet_address, wallet_private_key, location, hex_value, change_price=1_000_000_000_000_000):
nonce = w3.eth.getTransactionCount(wallet_address)
txn_dict = contract_etherdoek.functions.change_pixel_color(location,
hex_value).buildTransaction({'gasPrice': w3.toWei(gas_price, 'gwei'),
'nonce': nonce,
'value': change_price,
'chainId': chain_id,
'gas': 500_000})
signed_txn = w3.eth.account.signTransaction(txn_dict, wallet_private_key)
txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
txn_receipt = None
count = 0
while txn_receipt is None:
try:
txn_receipt = w3.eth.getTransactionReceipt(txn_hash)
except:
time.sleep(1)
if txn_receipt is None:
return {'status': 'failed', 'error': 'timeout'}
else:
return {'status': 'added', 'txn_receipt': txn_receipt}
def parse_log(contract, event, from_block=FROM_BLOCK):
# logs = contract.eventFilter(event, {'fromBlock': from_block}).get_all_entries() # web3.py v4
logs = getattr(contract.events, event).createFilter(fromBlock=from_block).get_all_entries() # web3.py v5
if len(logs) == 0:
return pd.DataFrame()
else:
df = pd.DataFrame(logs)
for key in df['args'].iloc[0].keys():
df[key] = df['args'].apply(lambda l: l[key])
df = df.drop(['args'], axis=1)
for column in ['address', 'blockHash', 'event', 'transactionHash']:
df[column] = df[column].astype(str)
return df
def hexbytes_to_rgb(hex_value):
return (int.from_bytes(hex_value[0:1], 'big'),
int.from_bytes(hex_value[1:2], 'big'),
int.from_bytes(hex_value[2:3], 'big'))
def create_df_pixel(web3_contract, from_block=FROM_BLOCK):
df_log_buy = parse_log(web3_contract, 'pixel_buy', from_block=from_block)
if len(df_log_buy) == 0:
return pd.DataFrame()
df_log_change = parse_log(web3_contract, 'pixel_change', from_block=from_block)
df_png = df_log_buy.append(df_log_change).drop_duplicates(subset=['location'],
keep='last').reset_index(drop=True)[['location', 'color']]
df_png.loc[:, 'location_0_x'] = df_png['location'].apply(lambda l: (l - 1) % 1_000)
df_png.loc[:, 'location_0_y'] = df_png['location'].apply(lambda l: int((l - 1) / 1_000))
df_png.loc[:, 'color_rgb'] = df_png['color'].apply(hexbytes_to_rgb)
return df_png
def create_doek(df_png):
png_out = Image.new('RGBA', (1_000, 1_000))
if len(df_png) == 0:
return png_out
for index, row in df_png.iterrows():
png_out.putpixel((row['location_0_x'], row['location_0_y']), row['color_rgb'])
return png_out
ABI
Etherdoek address
0x67B4Ef189A68133aB3a726b85d289B912C23e0B0
[
{
"name": "pixel_buy",
"inputs": [
{
"type": "uint256",
"name": "location",
"indexed": false
},
{
"type": "bytes",
"name": "color",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"name": "pixel_change",
"inputs": [
{
"type": "uint256",
"name": "location",
"indexed": false
},
{
"type": "bytes",
"name": "color",
"indexed": false
}
],
"anonymous": false,
"type": "event"
},
{
"outputs": [],
"inputs": [
{
"type": "address",
"name": "_pixel_token"
}
],
"constant": false,
"payable": false,
"type": "constructor"
},
{
"name": "change_contract_owner",
"outputs": [],
"inputs": [
{
"type": "address",
"name": "new_owner"
}
],
"constant": false,
"payable": false,
"type": "function",
"gas": 36247
},
{
"name": "set_fees",
"outputs": [],
"inputs": [
{
"type": "uint256",
"name": "_pixel_price"
},
{
"type": "uint256",
"name": "_pixel_change_fee"
}
],
"constant": false,
"payable": false,
"type": "function",
"gas": 71247
},
{
"name": "buy_pixel",
"outputs": [],
"inputs": [
{
"type": "uint256",
"name": "location"
},
{
"type": "bytes",
"name": "hex_value"
}
],
"constant": false,
"payable": true,
"type": "function",
"gas": 119741
},
{
"name": "change_pixel_color",
"outputs": [],
"inputs": [
{
"type": "uint256",
"name": "location"
},
{
"type": "bytes",
"name": "hex_value"
}
],
"constant": false,
"payable": true,
"type": "function",
"gas": 117802
},
{
"name": "pixel_token",
"outputs": [
{
"type": "address",
"name": ""
}
],
"inputs": [],
"constant": true,
"payable": false,
"type": "function",
"gas": 1271
},
{
"name": "pixel_price",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"constant": true,
"payable": false,
"type": "function",
"gas": 1301
},
{
"name": "pixel_change_fee",
"outputs": [
{
"type": "uint256",
"name": ""
}
],
"inputs": [],
"constant": true,
"payable": false,
"type": "function",
"gas": 1331
},
{
"name": "pixel_color",
"outputs": [
{
"type": "bytes",
"name": ""
}
],
"inputs": [
{
"type": "uint256",
"name": "arg0"
}
],
"constant": true,
"payable": false,
"type": "function",
"gas": 6901
}
]