Monorepo for Aesthetic.Computer aesthetic.computer
at main 113 lines 4.1 kB view raw
1#!/usr/bin/env node 2// Batch list Screenshots NFTs on OpenSea at $15 each 3// Usage: node list-screenshots.mjs [--dry-run] 4 5import { OpenSeaSDK, Chain } from 'opensea-js'; 6import { ethers } from 'ethers'; 7 8const SCREENSHOTS_CONTRACT = '0x651c6dc799864004a9df503db6a570c4c1cec743'; 9const PRICE_USD = 15; 10const WALLET_MNEMONIC = process.env.ETH_MNEMONIC; 11 12const TOKEN_IDS = [ 13 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35, 14 36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55, 15 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75, 16 76,77,78,79,80,81,83,84,85,86,87,88,89,90 17]; 18 19const dryRun = process.argv.includes('--dry-run'); 20 21async function main() { 22 if (!WALLET_MNEMONIC) { 23 console.error('❌ Set ETH_MNEMONIC env var (citizen wallet mnemonic)'); 24 process.exit(1); 25 } 26 27 // Get current ETH price 28 let ethUsd = 2174; // fallback 29 try { 30 const resp = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd'); 31 if (resp.ok) { 32 const d = await resp.json(); 33 ethUsd = d.ethereum?.usd || ethUsd; 34 } 35 } catch {} 36 37 const priceEth = PRICE_USD / ethUsd; 38 39 console.log('\n╔══════════════════════════════════════════════════════════════╗'); 40 console.log('║ 🖼️ Batch List Screenshots on OpenSea ║'); 41 console.log('╚══════════════════════════════════════════════════════════════╝\n'); 42 43 console.log(`📍 Contract: ${SCREENSHOTS_CONTRACT}`); 44 console.log(`🎨 Tokens: ${TOKEN_IDS.length}`); 45 console.log(`💵 Price: $${PRICE_USD} each (${priceEth.toFixed(6)} ETH @ $${ethUsd})`); 46 console.log(`💰 Total if sold: $${PRICE_USD * TOKEN_IDS.length}`); 47 console.log(`🔧 Mode: ${dryRun ? 'DRY RUN' : 'LIVE'}\n`); 48 49 // Set up wallet 50 const provider = new ethers.JsonRpcProvider('https://rpc.mevblocker.io'); 51 const wallet = ethers.Wallet.fromPhrase(WALLET_MNEMONIC).connect(provider); 52 console.log(`👤 Wallet: ${wallet.address}\n`); 53 54 // Set up OpenSea SDK 55 const sdk = new OpenSeaSDK(wallet, { 56 chain: Chain.Mainnet, 57 apiKey: process.env.OPENSEA_API_KEY, 58 }); 59 60 if (dryRun) { 61 console.log('⚠️ DRY RUN — no listings will be created.\n'); 62 console.log('Would list:'); 63 for (const id of TOKEN_IDS) { 64 console.log(` Screenshots #${id} @ ${priceEth.toFixed(6)} ETH ($${PRICE_USD})`); 65 } 66 console.log(`\nTotal: ${TOKEN_IDS.length} listings`); 67 return; 68 } 69 70 // Build bulk listings array — start with just first 3 as test 71 const testMode = process.argv.includes('--test'); 72 const idsToList = testMode ? TOKEN_IDS.slice(0, 3) : TOKEN_IDS; 73 const listings = idsToList.map(tokenId => ({ 74 asset: { 75 tokenId: tokenId.toString(), 76 tokenAddress: SCREENSHOTS_CONTRACT, 77 }, 78 amount: priceEth, 79 expirationTime: Math.round(Date.now() / 1000) + 90 * 24 * 60 * 60, // 90 days 80 })); 81 82 console.log(`📝 Submitting ${listings.length} bulk listings...\n`); 83 84 const result = await sdk.createBulkListings({ 85 listings, 86 accountAddress: wallet.address, 87 continueOnError: true, 88 onProgress: (completed, total) => { 89 process.stdout.write(`\r Progress: ${completed}/${total}`); 90 }, 91 }); 92 93 const success = result.successful?.length || 0; 94 const failed = result.failed?.length || 0; 95 const errors = result.failed || []; 96 97 console.log('\n'); 98 for (const s of (result.successes || [])) { 99 // just count, don't spam 100 } 101 102 console.log(`\n${'═'.repeat(50)}`); 103 console.log(`✅ Listed: ${success}`); 104 console.log(`❌ Failed: ${failed}`); 105 if (errors.length) { 106 console.log('\nErrors:'); 107 for (const e of errors) { 108 console.log(` ${JSON.stringify(e).slice(0, 100)}`); 109 } 110 } 111} 112 113main().catch(e => { console.error('❌', e.message); process.exit(1); });