Monorepo for Aesthetic.Computer
aesthetic.computer
1#!/usr/bin/env node
2
3/**
4 * Simple XTZ transfer between wallets
5 * Usage: node transfer.mjs <from-wallet> <to-address> <amount-in-xtz>
6 */
7
8import { TezosToolkit } from '@taquito/taquito';
9import { InMemorySigner } from '@taquito/signer';
10import fs from 'fs';
11import path from 'path';
12import { fileURLToPath } from 'url';
13
14const __filename = fileURLToPath(import.meta.url);
15const __dirname = path.dirname(__filename);
16
17const CONFIG = {
18 mainnet: {
19 name: 'Mainnet',
20 rpc: 'https://mainnet.api.tez.ie',
21 explorer: 'https://tzkt.io'
22 },
23 ghostnet: {
24 name: 'Ghostnet (Testnet)',
25 rpc: 'https://ghostnet.ecadinfra.com',
26 explorer: 'https://ghostnet.tzkt.io'
27 }
28};
29
30function loadCredentials(wallet) {
31 const walletPaths = {
32 kidlisp: { path: 'kidlisp/.env', addressKey: 'KIDLISP_ADDRESS', secretKey: 'KIDLISP_KEY' },
33 aesthetic: { path: 'kidlisp/.env', addressKey: 'AESTHETIC_ADDRESS', secretKey: 'AESTHETIC_KEY' },
34 staging: { path: 'staging/.env', addressKey: 'STAGING_ADDRESS', secretKey: 'STAGING_KEY' }
35 };
36
37 const walletConfig = walletPaths[wallet];
38 if (!walletConfig) {
39 throw new Error(`Unknown wallet: ${wallet}. Use: kidlisp, aesthetic, or staging`);
40 }
41
42 const envPath = path.join(__dirname, walletConfig.path);
43 if (!fs.existsSync(envPath)) {
44 throw new Error(`Wallet credentials not found: ${envPath}`);
45 }
46
47 const credentials = {};
48 const content = fs.readFileSync(envPath, 'utf8');
49 for (const line of content.split('\n')) {
50 if (line.startsWith(walletConfig.addressKey + '=') || line.startsWith('ADDRESS=')) {
51 credentials.address = line.split('=')[1].trim().replace(/"/g, '');
52 } else if (line.startsWith(walletConfig.secretKey + '=') || line.startsWith('KEY=') || line.startsWith('SECRET_KEY=')) {
53 credentials.secretKey = line.split('=')[1].trim().replace(/"/g, '');
54 }
55 }
56
57 if (!credentials.address || !credentials.secretKey) {
58 throw new Error(`Invalid credentials in ${envPath}`);
59 }
60
61 return credentials;
62}
63
64async function transfer(fromWallet, toAddress, amountXTZ, network = 'mainnet') {
65 console.log('\n╔══════════════════════════════════════════════════════════════╗');
66 console.log('║ 💸 XTZ Transfer ║');
67 console.log('╚══════════════════════════════════════════════════════════════╝\n');
68
69 const credentials = loadCredentials(fromWallet);
70 const config = CONFIG[network];
71 const tezos = new TezosToolkit(config.rpc);
72 tezos.setProvider({ signer: new InMemorySigner(credentials.secretKey) });
73
74 console.log(`📡 Network: ${config.name}`);
75 console.log(`👤 From: ${credentials.address} (${fromWallet})`);
76 console.log(`📥 To: ${toAddress}`);
77 console.log(`💰 Amount: ${amountXTZ} XTZ\n`);
78
79 // Check balance
80 console.log('💰 Checking balance...');
81 const balance = await tezos.tz.getBalance(credentials.address);
82 const balanceXTZ = balance.toNumber() / 1_000_000;
83 console.log(` Current balance: ${balanceXTZ.toFixed(6)} XTZ`);
84
85 if (balanceXTZ < amountXTZ) {
86 throw new Error(`Insufficient balance. Have ${balanceXTZ.toFixed(6)} XTZ, need ${amountXTZ} XTZ`);
87 }
88
89 // Send transfer
90 console.log('\n📤 Sending transfer...');
91 const op = await tezos.contract.transfer({
92 to: toAddress,
93 amount: amountXTZ
94 });
95
96 console.log(` ⏳ Operation hash: ${op.hash}`);
97 console.log(' ⏳ Waiting for confirmation...');
98
99 await op.confirmation(1);
100
101 console.log('\n✅ Transfer completed!');
102 console.log(` 🔗 Explorer: ${config.explorer}/${op.hash}\n`);
103
104 // Check new balance
105 const newBalance = await tezos.tz.getBalance(credentials.address);
106 const newBalanceXTZ = newBalance.toNumber() / 1_000_000;
107 console.log(` New balance: ${newBalanceXTZ.toFixed(6)} XTZ\n`);
108}
109
110// Parse CLI args
111const args = process.argv.slice(2);
112if (args.length < 3) {
113 console.error('Usage: node transfer.mjs <from-wallet> <to-address> <amount-in-xtz> [network]');
114 console.error('Example: node transfer.mjs aesthetic tz1dfoQDuxjwSgxdqJnisyKUxDHweade4Gzt 1.0 mainnet');
115 process.exit(1);
116}
117
118const [fromWallet, toAddress, amountStr, network = 'mainnet'] = args;
119const amount = parseFloat(amountStr);
120
121transfer(fromWallet, toAddress, amount, network).catch(err => {
122 console.error('\n❌ Transfer failed!');
123 console.error(` Error: ${err.message}\n`);
124 process.exit(1);
125});