Berry Club: Read the live board, then reconstruct one era
Use this walkthrough when the live board is easy to read, but you need one historical reconstruction path behind it.
Start with the live board. If that already answers the question, stop there.
Only switch to Transactions API when the question becomes historical: “what did Berry Club look like during one older era, and which draw calls made it look that way?”
These shell examples work against the public RPC and Transactions endpoints. If FASTNEAR_API_KEY is already set in your shell, the FastNear calls will forward it automatically as a bearer header.
Live Berry Club board
Refreshing live board from RPC...
Showing the latest saved snapshot while the live RPC read updates.
1. Read the live board
This is the shortest useful read:
ARGS_BASE64="$(jq -nc '{lines: [range(0;50)]}' | base64 | tr -d '\n')"
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi
curl -sS https://rpc.mainnet.fastnear.com \
"${AUTH_HEADER[@]}" \
-H 'content-type: application/json' \
--data "{
\"jsonrpc\": \"2.0\",
\"id\": \"berry-live-board\",
\"method\": \"query\",
\"params\": {
\"request_type\": \"call_function\",
\"finality\": \"final\",
\"account_id\": \"berryclub.ek.near\",
\"method_name\": \"get_lines\",
\"args_base64\": \"$ARGS_BASE64\"
}
}" | jq '.result | {block_height, line_count: (.result | implode | fromjson | length)}'That gives you the current 50x50 board from the contract itself. The only decode step is turning each returned base64 line into 50 pixel colors.
2. Reconstruct one older era
When you need history, keep the flow short:
- bound one era
- list candidate
drawtransactions forberryclub.ek.near - hydrate those hashes
- replay the
pixelsarrays oldest-first
This example uses a narrow window around block 97601515:
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi
curl -sS https://tx.main.fastnear.com/v0/account \
"${AUTH_HEADER[@]}" \
-H 'content-type: application/json' \
--data '{
"account_id": "berryclub.ek.near",
"is_function_call": true,
"is_receiver": true,
"is_real_receiver": true,
"from_tx_block_height": 97576515,
"to_tx_block_height": 97601516,
"desc": false,
"limit": 200
}' | jq '.account_txs | map({transaction_hash, tx_block_height}) | .[-5:]'If you do not know the window yet, /v0/blocks can help you choose one first. It is not part of the core Berry Club flow.
Hydrate the candidate hashes and keep only top-level draw calls:
AUTH_HEADER=()
if [ -n "${FASTNEAR_API_KEY:-}" ]; then AUTH_HEADER=(-H "Authorization: Bearer $FASTNEAR_API_KEY"); fi
curl -sS https://tx.main.fastnear.com/v0/transactions \
"${AUTH_HEADER[@]}" \
-H 'content-type: application/json' \
--data '{
"tx_hashes": [
"Hq5qwsuiM2emJrqczWM9awCa7o6sTBYqYpcifUX2SUhQ",
"8tBip5M2TrozhSyepAA3tYXpyKooi5t7b9c64wXjFvfL"
]
}' | jq '.transactions[]
| select(.transaction.receiver_id == "berryclub.ek.near")
| .transaction.actions[]?.FunctionCall
| select(.method_name == "draw")
| {method_name, args: (.args | @base64d | fromjson)}'Replay the pixels arrays oldest-first:
const board = Array.from({ length: 50 }, () => Array(50).fill(0));
for (const drawTx of drawTransactionsOldestFirst) {
for (const pixel of drawTx.args.pixels) {
if (pixel.x < 0 || pixel.x >= 50 || pixel.y < 0 || pixel.y >= 50) {
continue;
}
board[pixel.y][pixel.x] = pixel.color;
}
}That is the whole historical pattern. Berry Club does not expose a ready-made “board at block N” endpoint, so older eras come from replaying draw writes.