Skip to content
Closed
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
181 changes: 181 additions & 0 deletions scripts/renew-all-domains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/**
* Domain Renewal Script
* Renews all domains in the MetaNames contract for 1 extra year
*
* Usage:
* npx tsx scripts/renew-all-domains.ts
*
* Environment:
* ADMIN_PRIVATE_KEY - The admin account private key (required)
*/

import { ethers } from 'ethers';

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
import * as fs from 'fs';

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
import * as path from 'path';

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// Config - MetaNames Mainnet
const CONTRACT_ADDRESS = '02c9a6290864e27b587331c88ec8e69a8280c290dc';

Check failure

Code scanning / ESLint

Disallow unused variables Error

'CONTRACT_ADDRESS' is assigned a value but never used.

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const RPC_URL = process.env.RPC_URL || 'https://rpc.partisiablockchain.com';

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const LOG_DIR = path.join(process.cwd(), 'logs');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

const RPC_URL = process.env.RPC_URL || 'https://rpc.partisiablockchain.com';

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const LOG_DIR = path.join(process.cwd(), 'logs');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const RETRY_DELAYS = [2000, 4000, 8000]; // Exponential backoff

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

interface RenewalLog {
timestamp: string;
domain: string;
txHash: string;
status: 'SUCCESS' | 'FAILED';
error?: string;
}

function getLogFile(): string {
const date = new Date().toISOString().split('T')[0];

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
return path.join(LOG_DIR, `renewals-${date}.csv`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

function initLogFile(): void {
if (!fs.existsSync(LOG_DIR)) {
fs.mkdirSync(LOG_DIR, { recursive: true });

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}
const logFile = getLogFile();

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
if (!fs.existsSync(logFile)) {
fs.writeFileSync(logFile, 'timestamp,domain,txHash,status,error\n');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}
}

function appendLog(entry: RenewalLog): void {
const logFile = getLogFile();

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const row = `${entry.timestamp},${entry.domain},${entry.txHash},${entry.status},${entry.error || ''}\n`;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
fs.appendFileSync(logFile, row);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

async function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

async function renewDomain(

Check failure

Code scanning / ESLint

Disallow unused variables Error

'renewDomain' is defined but never used.
contract: ethers.Contract,
domain: string,
signer: ethers.Signer
): Promise<{ txHash: string; success: boolean; error?: string }> {
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
// Send transaction with hardcoded gas limit (2100 is sufficient for renewal)
const tx = await contract.renew(domain, {
gasLimit: 2100,
gasPrice: await signer.provider!.getGasPrice()

Check failure

Code scanning / ESLint

Disallow non-null assertions using the `!` postfix operator Error

Forbidden non-null assertion.
});

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

console.log(` Tx sent: ${tx.hash}, waiting for confirmation...`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// Wait for transaction to be confirmed
const receipt = await tx.wait();

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

if (receipt.status === 1) {
return { txHash: tx.hash, success: true };

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
} else {
return { txHash: tx.hash, success: false, error: 'Transaction failed' };

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}
} catch (error: any) {

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const errorMsg = error.message || String(error);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(` Attempt ${attempt + 1} failed: ${errorMsg}`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// Check if it's a transient error
const isTransient =
error.code === 'NETWORK_ERROR' ||
error.code === 'TIMEOUT' ||
error.message?.includes('nonce') ||
error.message?.includes('gas');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

if (isTransient && attempt < MAX_RETRIES - 1) {
console.log(` Retrying in ${RETRY_DELAYS[attempt]}ms...`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
await sleep(RETRY_DELAYS[attempt]);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
continue;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

return { txHash: '', success: false, error: errorMsg };

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}
}

return { txHash: '', success: false, error: 'Max retries exceeded' };

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

async function main() {
const privateKey = process.env.ADMIN_PRIVATE_KEY;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
if (!privateKey) {
console.error('ERROR: ADMIN_PRIVATE_KEY environment variable is required');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log('Set it with: export ADMIN_PRIVATE_KEY="0x..."');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
process.exit(1);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

initLogFile();

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// Setup provider and signer
const provider = new ethers.JsonRpcProvider(RPC_URL);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
const signer = new ethers.Wallet(privateKey, provider);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

console.log(`Using admin address: ${signer.address}`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(`RPC: ${RPC_URL}\n`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// TODO: Connect to the actual contract
// const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);

// TODO: Get all domains from contract
// const domains = await contract.getAllDomains();

// Placeholder for testing
const domains = [
'example.meta',
'test.meta'
];

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

console.log(`Found ${domains.length} domains to renew\n`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

const results: RenewalLog[] = [];

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
let successCount = 0;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
let failCount = 0;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

for (const domain of domains) {
console.log(`Renewing ${domain}...`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

// TODO: Uncomment when contract is connected
// const result = await renewDomain(contract, domain, signer);

// Placeholder result for now
const result = {
txHash: '0xplaceholder',
success: true
};

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

const entry: RenewalLog = {
timestamp: new Date().toISOString(),
domain,
txHash: result.txHash,
status: result.success ? 'SUCCESS' : 'FAILED',
error: result.success ? undefined : result.error
};

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

appendLog(entry);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
results.push(entry);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.

if (result.success) {
successCount++;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(` ✓ ${domain} renewed\n`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
} else {
failCount++;

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(` ✗ ${domain} failed: ${result.error}\n`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

// Small delay between domains to avoid rate limiting
await sleep(500);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

console.log('--- Summary ---');

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(`Succeeded: ${successCount}`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(`Failed: ${failCount}`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
console.log(`Log file: ${getLogFile()}`);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
}

main().catch(console.error);

Check failure

Code scanning / ESLint

Require or disallow semicolons instead of ASI Error

Extra semicolon.
Loading