Cloudflare Workers backend for clip attribution with persistent wallet identity + reward ledger balances.
bun install
bun run devbun run deployRun tests:
bun run testCopy .env.example values into your deployed worker secrets.
Required:
DATABASE_URLSHOPIFY_WEBHOOK_SECRET
Wallet pass provider (optional, server-side only):
WALLETWALLET_API_KEYWALLETWALLET_BASE_URL(defaults tohttps://api.walletwallet.dev)PUBLIC_API_BASE_URL(recommended, e.g.https://api.clipstakes.app)PUBLIC_VIDEO_BASE_URL(optional, e.g.https://cdn.clipstakes.app/clips)
wallet.pass_url is always generated by the backend and points to GET /wallet/:wallet_code/pass.
When WalletWallet is unavailable, local pass signing requires:
WALLET_PASS_TYPE_IDWALLET_TEAM_IDWALLET_CERT(base64 PKCS#12)WALLET_CERT_PASSWORDWALLET_WWDR_CERT(PEM or base64 PEM intermediate cert)
Optional pass branding:
WALLET_ORGANIZATION_NAMEWALLET_PASS_DESCRIPTIONWALLET_PASS_LOGO_TEXT
Apply migrations in order, including:
sql/migrations/20260307_coupon_wallet.sql
sql/migrations/20260307_wallet_ledger.sqlThe wallet-ledger migration adds:
creator_wallets(one wallet identity per user)conversions(provider order dedupe)reward_transactions(credits + debits ledger with idempotency key)
Device identity is anonymous via request header:
X-Device-ID: <stable-device-id>Primary reward flow:
POST /clipscreates the clip and creditsclip_published(+500 cents).POST /conversionsandPOST /conversions/devcredit every unique conversion (+500 cents) even after 8 hours.- 8-hour window controls push urgency only (
push.within_window), not reward eligibility. GET /rewards/mereturns wallet identity, balances, and recent ledger transactions.POST /wallet/redeemdebits balance for cashier/POS redemption.GET /wallet/:wallet_code/balancesupports scanner-side balance lookup.
Compatibility:
POST /uploadandPOST /upload-urlare both supported.upload_urlandvideo_urlare absolute HTTPS URLs generated by the backend.- Legacy coupon route
/coupons/redeemremains available for previously issued coupons.