UNPKG

filecoin-pin

Version:

Bridge IPFS content to Filecoin Onchain Cloud using familiar tools

136 lines 6.73 kB
/** * Automatic payment setup flow * * This module provides an automated, non-interactive setup experience for * configuring payment approvals. It uses default values and command-line * options to complete the setup without user interaction. */ import { ethers } from 'ethers'; import pc from 'picocolors'; import { TELEMETRY_CLI_APP_NAME } from '../common/constants.js'; import { calculateDepositCapacity, checkAndSetAllowances, checkFILBalance, checkUSDFCBalance, depositUSDFC, getPaymentStatus, validatePaymentRequirements, } from '../core/payments/index.js'; import { cleanupSynapseService, initializeSynapse } from '../core/synapse/index.js'; import { formatUSDFC } from '../core/utils/format.js'; import { getCLILogger, parseCLIAuth } from '../utils/cli-auth.js'; import { cancel, createSpinner, intro, outro } from '../utils/cli-helpers.js'; import { log } from '../utils/cli-logger.js'; import { displayAccountInfo, displayDepositWarning } from './setup.js'; /** * Run automatic payment setup with defaults * * @param options - Options from command line */ export async function runAutoSetup(options) { intro(pc.bold('Filecoin Onchain Cloud Payment Setup')); log.message(pc.gray('Running in auto mode...')); // Parse and validate deposit amount let targetFilecoinPayBalance; try { targetFilecoinPayBalance = ethers.parseUnits(options.deposit, 18); } catch { console.error(pc.red(`Error: Invalid deposit amount '${options.deposit}'`)); process.exit(1); } const spinner = createSpinner(); spinner.start('Initializing connection...'); try { // Parse and validate authentication const authConfig = parseCLIAuth(options); const logger = getCLILogger(); const synapse = await initializeSynapse({ ...authConfig, telemetry: { sentrySetTags: { appName: TELEMETRY_CLI_APP_NAME } } }, logger); const network = synapse.getNetwork(); const client = synapse.getClient(); const address = await client.getAddress(); spinner.stop(`${pc.green('✓')} Connected to ${pc.bold(network)}`); // Check balances spinner.start('Checking balances...'); const filStatus = await checkFILBalance(synapse); const walletUsdfcBalance = await checkUSDFCBalance(synapse); spinner.stop(`${pc.green('✓')} Balance check complete`); // Validate payment requirements const validation = validatePaymentRequirements(filStatus.hasSufficientGas, walletUsdfcBalance, filStatus.isCalibnet); if (!validation.isValid) { log.line(`${pc.red('✗')} ${validation.errorMessage}`); if (validation.helpMessage) { log.line(''); log.line(` ${pc.cyan(validation.helpMessage)}`); } log.flush(); cancel('Please fund your wallet and try again'); process.exit(1); } // Now safe to get payment status since we know account exists const status = await getPaymentStatus(synapse); // Display account and balance info using shared function displayAccountInfo(address, network, filStatus.balance, filStatus.isCalibnet, filStatus.hasSufficientGas, walletUsdfcBalance, status.filecoinPayBalance); // Get storage pricing for capacity calculation const storageInfo = await synapse.storage.getStorageInfo(); const pricePerTiBPerEpoch = storageInfo.pricing.noCDN.perTiBPerEpoch; // Track if any changes were made let actionsTaken = false; let actualFilecoinPayTopUp = 0n; if (status.filecoinPayBalance < targetFilecoinPayBalance) { const neededFilecoinPayTopUp = targetFilecoinPayBalance - status.filecoinPayBalance; actualFilecoinPayTopUp = neededFilecoinPayTopUp; if (neededFilecoinPayTopUp > walletUsdfcBalance) { console.error(pc.red(`✗ Insufficient USDFC for deposit (need ${formatUSDFC(neededFilecoinPayTopUp)} USDFC, have ${formatUSDFC(walletUsdfcBalance)} USDFC)`)); process.exit(1); } spinner.start(`Depositing ${formatUSDFC(neededFilecoinPayTopUp)} USDFC...`); const { depositTx } = await depositUSDFC(synapse, neededFilecoinPayTopUp); spinner.stop(`${pc.green('✓')} Deposited ${formatUSDFC(neededFilecoinPayTopUp)} USDFC`); actionsTaken = true; log.line(pc.bold('Transaction details:')); log.indent(pc.gray(`Deposit: ${depositTx}`)); log.flush(); } else { // Use a dummy spinner to get consistent formatting spinner.start('Checking deposit...'); const { updated, transactionHash } = await checkAndSetAllowances(synapse); if (updated) { spinner.stop(`${pc.green('✓')} Updated payment allowances, tx: ${transactionHash}`); } else { spinner.stop(`${pc.green('✓')} Deposit already sufficient (${formatUSDFC(status.filecoinPayBalance)} USDFC)`); } } // Calculate capacity for final summary const totalDeposit = status.filecoinPayBalance + actualFilecoinPayTopUp; const capacity = calculateDepositCapacity(totalDeposit, pricePerTiBPerEpoch); // Final summary spinner.start('Completing setup...'); spinner.stop('━━━ Configuration Summary ━━━'); log.line(`Network: ${pc.bold(network)}`); log.line(`Deposit: ${formatUSDFC(totalDeposit)} USDFC`); if (capacity.gibPerMonth > 0) { const capacityStr = capacity.gibPerMonth >= 1024 ? `${(capacity.gibPerMonth / 1024).toFixed(1)} TiB` : `${capacity.gibPerMonth.toFixed(1)} GiB`; log.line(`Storage: ~${capacityStr} for 1 month`); } log.line(`Status: ${pc.green('Ready to upload')}`); log.flush(); // Show deposit warning if needed displayDepositWarning(totalDeposit, status.currentAllowances.lockupUsed); // Show appropriate outro message based on whether actions were taken if (actionsTaken) { outro('Payment setup completed successfully'); } else { outro('Payment setup already configured - ready to use'); } } catch (error) { spinner.stop(); // Stop spinner without message console.error(pc.red('✗ Setup failed')); console.error(pc.red('Error:'), error instanceof Error ? error.message : error); process.exitCode = 1; } finally { await cleanupSynapseService(); process.exit(); } } //# sourceMappingURL=auto.js.map