Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions gauntlet-coa-autopost/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# TrueCOA Auto-Post NFT Pipeline

Auto-mint NFTs, create ScoreDetect certificates, and list on OpenSea when a new COA row is filled in Google Sheets.

## Flow

```
Google Sheet edit → GAS trigger → Backend webhook → Mint NFT on Polygon →
ScoreDetect certificate → OpenSea auto-indexes → Results written back to sheet
```

## New Files

| File | Purpose |
|------|---------|
| `backend/services/nftMinter.js` | Mint NFTs on Polygon via ethers.js (queued, nonce-safe) |
| `backend/services/scoreDetect.js` | ScoreDetect blockchain certification API |
| `backend/services/sheetWriter.js` | Write results back to Google Sheets (read/write scope) |
| `backend/services/automationPipeline.js` | Orchestrates the full pipeline per row |
| `backend/routes/automation.js` | Express routes: webhook, poll, retry, status |
| `google-apps-script/AutoPostTrigger.gs` | GAS installable trigger + menu for auto-post |

## Modified Files

| File | Changes |
|------|---------|
| `backend/index.js` | Added automation routes, sheets writer init, cron polling |
| `backend/package.json` | Added `node-cron` dependency |
| `backend/.env.example` | Added auto-post environment variables |

## Setup

### 1. Railway Environment Variables

Add to your Railway backend deployment:

```env
PRIVATE_KEY=your_polygon_wallet_private_key
MINT_RECIPIENT=0xYourGalleryWalletAddress
WEBHOOK_SECRET=your-random-secret-string
SCOREDETECT_API_KEY=your-scoredetect-key
OPENSEA_API_KEY=your-opensea-key # optional
POLL_INTERVAL=*/3 * * * * # optional, default 3 min
```

### 2. Google Sheets Scope

The service account now needs **read/write** access to the spreadsheet (not just Viewer).
Share the sheet with the service account email as **Editor**.

### 3. Google Apps Script

1. Open your COA2 Google Sheet
2. Extensions > Apps Script
3. Create a new file: `AutoPostTrigger.gs`
4. Paste contents of `google-apps-script/AutoPostTrigger.gs`
5. Set Script Properties (File > Project settings > Script properties):
- `WEBHOOK_URL` = `https://coa.up.railway.app/api/automate`
- `WEBHOOK_SECRET` = (same secret as Railway)
6. Run `setupAutoPostTrigger()` once from the editor

### 4. Deploy Backend

```bash
cd backend
npm install
# Push to Railway (auto-deploys on git push)
```

## API Endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/automate/:coaCode` | POST | Webhook - process single COA |
| `/api/automate/poll` | POST | Manually trigger poll for all unprocessed rows |
| `/api/automate/retry/:coaCode` | POST | Retry a failed COA |
| `/api/automate/status` | GET | Pipeline status, wallet balance, config check |

## How It Works

1. **You edit a row** in the COA2 sheet (add artist, title, etc.)
2. **GAS trigger fires** → calls backend webhook with the COA code
3. **Backend processes**:
- Validates required fields
- Mints NFT on Polygon (queued to prevent nonce collisions)
- Creates ScoreDetect blockchain certificate
- Triggers OpenSea metadata refresh
- Writes token ID, URLs, and timestamp back to the sheet
4. **Polling fallback** runs every 3 minutes to catch anything the trigger missed

## Sheet Column Mapping (COA2, 21 columns A-U)

| Column | Index | Field | Description |
|--------|-------|-------|-------------|
| A | 0 | COA_CODE | COA identifier |
| B | 1 | QR_CODE | QR code image URL (output) |
| C | 2 | SIGNER | Artist / signer name |
| D | 3 | TITLE | Artwork title |
| E | 4 | DATE | Date of artwork |
| F | 5 | SIZE | Dimensions |
| G | 6 | CONDITION | Condition of artwork |
| H | 7 | DESCRIPTION | Description |
| I | 8 | PROVENANCE | Provenance (header: "Provience") |
| J | 9 | EDITION | Edition info |
| K | 10 | MEDIUM | Medium |
| L | 11 | ASSIGNEE | Assignee |
| M | 12 | THIRD_PARTY_AUTH_NOTES | Third party auth notes |
| N | 13 | IMAGE_URL | Image URL |
| O | 14 | NFT_TOKEN_ID | NFT token ID (output) |
| P | 15 | SHORT_URL | Bit.ly short URL (output) |
| Q | 16 | BLOCKCHAIN_URL | Polygonscan URL (output) |
| R | 17 | NFT_URL | OpenSea URL (output) |
| S | 18 | CERT_URL | ScoreDetect certificate URL (output) |
| T | 19 | STATUS | Status / Done timestamp (output) |
| U | 20 | COMPLETION_DATE | Completion timestamp (output) |
42 changes: 42 additions & 0 deletions gauntlet-coa-autopost/backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Google Sheets Configuration
SPREADSHEET_ID=16Kya2WQD0tbXTdsug9zSuoP03XmWXsZRTIykbEbBJBU
SHEET_NAME=COA

# Google Service Account Credentials (JSON string)
# Get this from Google Cloud Console > APIs & Services > Credentials
GOOGLE_CREDENTIALS={"type":"service_account","project_id":"your-project",...}

# Polygon Configuration
# For Amoy Testnet:
POLYGON_RPC=https://rpc-amoy.polygon.technology
# For Mainnet (later):
# POLYGON_RPC=https://polygon-rpc.com

# Smart Contract Address (fill after deployment)
CONTRACT_ADDRESS=

# Server Port
PORT=3001

# ============================================================================
# AUTO-POST NFT PIPELINE (new)
# ============================================================================

# Polygon wallet private key for NFT minting (contract owner)
# NEVER commit this to git - set in Railway environment only
PRIVATE_KEY=

# Default wallet address to receive minted NFTs
MINT_RECIPIENT=0xYourGalleryWalletAddress

# Shared secret for Google Apps Script webhook authentication
WEBHOOK_SECRET=your-random-secret-string

# ScoreDetect API key for blockchain certification
SCOREDETECT_API_KEY=

# OpenSea API key for metadata refresh (optional, get from opensea.io/account/developer)
OPENSEA_API_KEY=

# Polling interval (cron expression, default: every 3 minutes)
POLL_INTERVAL=*/3 * * * *
Loading
Loading