Monorepo for Aesthetic.Computer
aesthetic.computer
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); });