How to Run Your Own Hive Gift Card Service
So you want to onboard new users to Hive by giving them gift cards? This guide walks you through setting up and running your own instance of the Propolis gift card service — the backend that turns single-use claim tokens into fully functional Hive accounts.
What You're Building
The gift card service is an Express.js application that:
- Generates batches of gift cards as QR codes (with PINs)
- Publishes cryptographic batch declarations on-chain for transparency
- Redeems claim tokens by creating Hive accounts with delegated HP
- Provides a dashboard API for managing batches
When a new user scans a gift card QR code, they're taken to the invite app where they choose a username and generate their keys locally. The invite app then calls your gift card service to create the account. The user's private keys never touch your server.
Prerequisites
Before you start, you'll need:
- A Hive account with claimed account tokens — These are created by spending RC (Resource Credits). The more HP your account has, the more tokens you can claim. You need one token per gift card.
- Your account's active key (WIF format) — Required to execute
create_claimed_accountoperations. - Your account's memo key (WIF format) — Used to cryptographically sign batches.
- Node.js 22+ installed.
- A server or hosting platform — Fly.io works well, but any platform that supports Docker and persistent storage will do.
Claiming Account Creation Tokens
Before you can create accounts for gift card recipients, you need to claim account creation tokens. This is done by spending your account's Resource Credits:
- Go to PeakD or use the CLI
- Use the
claim_accountoperation with your account - Each token costs approximately 27 billion RC
- You need one token per gift card you plan to distribute
You can check your pending token count at https://api.hive.blog by calling condenser_api.get_accounts with your username.
Step 1: Clone and Install
git clone https://github.com/demotruk/HiveAccessibleAnywhere.git
cd HiveAccessibleAnywhere/giftcard
npm install
Step 2: Configure Environment Variables
Copy the example environment file:
cp .env.example .env
Edit .env with your values:
# Your Hive account that owns the claimed account tokens
GIFTCARD_PROVIDER_ACCOUNT=your-hive-account
# Your account's active key (WIF format, starts with 5K/5J/5H)
GIFTCARD_ACTIVE_KEY=5K...
# Your account's memo key (WIF format)
GIFTCARD_MEMO_KEY=5K...
# The HAA feed/discovery service account
HAA_SERVICE_ACCOUNT=haa-service
# How much HP to delegate to each new account (in VESTS)
# 30000 VESTS is roughly 15 HP — enough for a new user to transact
GIFTCARD_DELEGATION_VESTS=30000.000000 VESTS
# Port for the service
PORT=3200
Important: Keep your .env file secure. Never commit it to version control.
Optional: Enable the Dashboard
If you want a web dashboard for generating and managing batches:
# Any random string — used to sign JWT session tokens
GIFTCARD_JWT_SECRET=generate-a-strong-random-secret-here
Optional: Custom Hive Nodes
By default the service uses public Hive API nodes. You can specify your own:
HIVE_NODES=https://api.hive.blog,https://api.deathwing.me,https://hive-api.arcange.eu
Step 3: Run Locally
For development:
npm run dev
This starts the service on http://localhost:3200 with auto-reload.
For production:
npm start
Verify it's running by visiting http://localhost:3200/health — you should get a 200 response.
Step 4: Generate Your First Batch
You have two options for generating gift cards: the dashboard API or the CLI script.
Option A: Using the CLI Script
The standalone script doesn't require the service to be running:
cd ../scripts
npx tsx giftcard-generate.ts --count 10 --expiry-days 365
This will:
- Generate 10 tokens and PINs
- Build a Merkle tree and compute the root
- Sign the batch with your memo key
- Broadcast the batch declaration on-chain
- Generate QR codes and PDFs
Output goes to the configured output directory. You'll get:
- A PDF with printable gift cards (each with a QR code and PIN)
- A manifest.json containing all card details (keep this secure — it contains PINs)
Use --dry-run to test without broadcasting anything on-chain.
Option B: Using the Dashboard API
If you enabled the dashboard (set GIFTCARD_JWT_SECRET), you can use the API:
Authenticate via Hive Keychain challenge-response:
POST /auth/challenge { "username": "your-account" } POST /auth/verify { "username": "...", "challenge": "...", "signature": "..." }Prepare a batch (generates tokens and Merkle tree):
POST /api/batches/prepare { "count": 10, "expiryDays": 365 }Sign the canonical string returned in the response using Hive Keychain.
Finalize the batch (generates QR codes, PDFs, and broadcasts on-chain):
POST /api/batches/:id/finalize { "signature": "..." }Download the PDF and manifest:
GET /api/batches/:id/pdf GET /api/batches/:id/manifest
Step 5: Deploy to Production
Using Docker
Build the image:
docker build -t hive-giftcard-service .
Run it:
docker run -d \
--name giftcard \
-p 3200:3200 \
--env-file .env \
-v giftcard-data:/data \
hive-giftcard-service
The -v giftcard-data:/data flag is critical — it persists the SQLite database across container restarts. Without it, you'll lose your token records.
Using Fly.io
Fly.io is a good fit because it supports persistent volumes and scales to zero when idle:
- Install the Fly CLI:
curl -L https://fly.io/install.sh | sh - Create the app:
fly apps create your-giftcard-service - Create a persistent volume:
fly volumes create giftcard_data --size 1 --region your-region - Set secrets:
fly secrets set \ GIFTCARD_PROVIDER_ACCOUNT=your-account \ GIFTCARD_ACTIVE_KEY=5K... \ GIFTCARD_MEMO_KEY=5K... \ HAA_SERVICE_ACCOUNT=haa-service \ GIFTCARD_DELEGATION_VESTS="30000.000000 VESTS" \ GIFTCARD_JWT_SECRET=your-secret - Deploy:
fly deploy
Make sure your fly.toml mounts the volume at /data.
Step 6: Distribute Cards
Once you've generated a batch, you have several distribution options:
- Print physical cards — Use the generated PDF. Each card has a QR code and a PIN printed on it.
- Digital distribution — Share the QR code images electronically (email, messaging apps, etc.).
- Telegram/Discord bot — Load the manifest into a bot that distributes cards on demand. The repo includes a bot implementation in
telegram-bot/that handles this.
How the Claim Flow Works
When a recipient uses a gift card:
- They scan the QR code, which opens the invite app with an encrypted payload in the URL
- They enter the PIN printed on the card
- The invite app decrypts the payload locally (keys are never sent to the server)
- They choose a Hive username and their keys are generated in the browser
- The invite app calls your service's
/claimendpoint - Your service validates the token against the on-chain Merkle proof, creates the account, and delegates HP
- The user now has a working Hive account
Security Notes
- Keys are generated client-side in the invite app. Your service never sees private keys.
- Tokens are validated cryptographically via Merkle proofs against on-chain batch declarations. Even if your database is compromised, forged tokens can't pass verification.
- Each token can only be used once. The service tracks spent token hashes to prevent double-spending.
- Rate limiting is applied to all endpoints to prevent abuse (10 claims/min, 30 validations/min per IP).
- Keep your active key secure. It has the authority to create accounts and manage delegations. Consider running the service on infrastructure you control.
Monitoring
The service exposes a /health endpoint for uptime monitoring. For a production deployment, you should:
- Monitor the health endpoint
- Track your remaining claimed account tokens (you'll need to claim more as they're used)
- Keep an eye on your account's RC and HP levels to ensure you can continue claiming tokens and delegating HP
Troubleshooting
"Insufficient RC" — Your account doesn't have enough Resource Credits to claim account tokens. Delegate more HP to your account or power up more HIVE.
"No pending claimed accounts" — You've used all your claimed account tokens. Claim more using the claim_account operation before generating new batches.
"Token already spent" — The gift card has already been redeemed. Each token can only be used once.
"Username taken" — The recipient chose a username that already exists on Hive. They'll need to pick a different one.
Database errors — Make sure your persistent volume is mounted correctly. The SQLite database at /data/tokens.db must survive container restarts.
If you have questions or run into issues, post in the HiveInvite community on Hive, or check the GitHub repository.