create pool from prices script update to use a cast command

This commit is contained in:
2025-11-17 14:12:34 -04:00
parent d5c40b9667
commit bd430411bd

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env node #!/usr/bin/env node
/** /**
* Create Pool from Real-Time Prices Script * Create Pool from Real-Time Prices Script
* Fetches real-time prices from CoinGecko and creates a new pool on Anvil * Fetches real-time prices from CoinGecko and creates a new pool on the chain specified (could be mockchain, sepolia or prod)
*/ */
import { ethers } from 'ethers'; import { ethers } from 'ethers';
@@ -12,28 +12,27 @@ import IPartyPlannerABI from "../src/contracts/IPartyPlannerABI.ts";
// CONFIGURATION // CONFIGURATION
// ============================================================================ // ============================================================================
const ANVIL_RPC_URL = 'http://127.0.0.1:8545'; const RPC_URL = "https://eth-sepolia.g.alchemy.com/v2/sJ7rLYKJzdRqXUs9cOiLVvHN8aTI30dn"
// Hardcoded private key for Anvil testing (default Anvil account #4 - payer) // sepolia dev wallet
const PRIVATE_KEY = '0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a'; const PRIVATE_KEY = '89c8f2542b5ff7f3cf0b73255e0a8d79d89c2be598e7f272a275a380ff56a212';
// Receiver address (Anvil account #7) const RECEIVER_ADDRESS = '0xd3b310bd32d782f89eea49cb79656bcaccde7213';
const RECEIVER_ADDRESS = '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955';
// Test token addresses (mapping to real coins) // Test token addresses (mapping to real coins)
const TEST_TOKENS = { const TEST_TOKENS = {
USDC: { USDC: {
address: '0xbdEd0D2bf404bdcBa897a74E6657f1f12e5C6fb6', // USXD (mock) = USDC (real) address: '0xCb2F4B07eFe0F06264AD28590aC7f03D5cdb0729', // USXD (mock) = USDC (real)
coingeckoId: 'usd-coin', coingeckoId: 'usd-coin',
decimals: 6 decimals: 6
}, },
BTC: { BTC: {
address: '0x93C7a6D00849c44Ef3E92E95DCEFfccd447909Ae', // BUTC (mock) = BTC (real) address: '0x19Ba3A189dc3DEbC07ADF7757dc8170702E91696', // BUTC (mock) = BTC (real)
coingeckoId: 'bitcoin', coingeckoId: 'bitcoin',
decimals: 8 decimals: 8
}, },
WETH: { WETH: {
address: '0x71a9d115E322467147391c4a71D85F8e1cA623EF', // WTETH (mock) = WETH (real) address: '0xd406e1a6b028D17b72f826E45bF36BB8Ad4077dB', // WTETH (mock) = WETH (real)
coingeckoId: 'weth', coingeckoId: 'weth',
decimals: 18 decimals: 18
} }
@@ -44,7 +43,11 @@ const DEFAULT_POOL_PARAMS = {
name: 'Balanced Portfolio Pool', name: 'Balanced Portfolio Pool',
symbol: 'BPP', symbol: 'BPP',
kappa: ethers.BigNumber.from('100000000000000000'), // 0.1 * 1e18 = 1e17 kappa: ethers.BigNumber.from('100000000000000000'), // 0.1 * 1e18 = 1e17
swapFeePpm: 3000, // 0.3% swapFeesPpm: [
50, // 0.0050%
2450, // 0.2450%
2950, // 0.2950%
],
flashFeePpm: 5, // 0.0005% flashFeePpm: 5, // 0.0005%
stable: false, stable: false,
initialLpAmount: ethers.BigNumber.from('1000000000000000000') // 1e18 initialLpAmount: ethers.BigNumber.from('1000000000000000000') // 1e18
@@ -58,9 +61,8 @@ const INPUT_USD_AMOUNT = 100;
// LOAD ABIs AND CONFIG // LOAD ABIs AND CONFIG
// ============================================================================ // ============================================================================
// Load chain info and get PartyPlanner address (chain ID 31337 = Anvil)
const chainInfoData = JSON.parse(await readFile(new URL('../src/contracts/liqp-deployments.json', import.meta.url), 'utf-8')); const chainInfoData = JSON.parse(await readFile(new URL('../src/contracts/liqp-deployments.json', import.meta.url), 'utf-8'));
const PARTY_PLANNER_ADDRESS = chainInfoData['31337'].v1.PartyPlanner; const PARTY_PLANNER_ADDRESS = chainInfoData['11155111'].v1.PartyPlanner;
const ERC20ABI = [ const ERC20ABI = [
{ "type": "function", "name": "balanceOf", "stateMutability": "view", "inputs": [{ "name": "account", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] }, { "type": "function", "name": "balanceOf", "stateMutability": "view", "inputs": [{ "name": "account", "type": "address" }], "outputs": [{ "name": "", "type": "uint256" }] },
@@ -205,13 +207,11 @@ async function approveTokens(wallet, tokenAmounts) {
} }
/** /**
* Create a new pool * Create a new pool using cast send
*/ */
async function createPool(wallet, tokenAmounts) { async function createPool(wallet, tokenAmounts) {
console.log(`\n[~] Creating new pool...`); console.log(`\n[~] Creating new pool...`);
const partyPlanner = new ethers.Contract(PARTY_PLANNER_ADDRESS, IPartyPlannerABI, wallet);
// Prepare parameters // Prepare parameters
const tokenAddresses = [ const tokenAddresses = [
TEST_TOKENS.USDC.address, TEST_TOKENS.USDC.address,
@@ -220,9 +220,9 @@ async function createPool(wallet, tokenAmounts) {
]; ];
const initialDeposits = [ const initialDeposits = [
tokenAmounts.USDC, tokenAmounts.USDC.toString(),
tokenAmounts.BTC, tokenAmounts.BTC.toString(),
tokenAmounts.WETH tokenAmounts.WETH.toString()
]; ];
// Set deadline to 1 hour from now // Set deadline to 1 hour from now
@@ -232,53 +232,45 @@ async function createPool(wallet, tokenAmounts) {
console.log(` Name: ${DEFAULT_POOL_PARAMS.name}`); console.log(` Name: ${DEFAULT_POOL_PARAMS.name}`);
console.log(` Symbol: ${DEFAULT_POOL_PARAMS.symbol}`); console.log(` Symbol: ${DEFAULT_POOL_PARAMS.symbol}`);
console.log(` Tokens: ${tokenAddresses.join(', ')}`); console.log(` Tokens: ${tokenAddresses.join(', ')}`);
console.log(` Swap Fees PPM: [${DEFAULT_POOL_PARAMS.swapFeesPpm.join(', ')}]`);
console.log(` Payer: ${wallet.address}`); console.log(` Payer: ${wallet.address}`);
console.log(` Receiver: ${RECEIVER_ADDRESS}`); console.log(` Receiver: ${RECEIVER_ADDRESS}`);
console.log(` Deadline: ${new Date(deadline * 1000).toISOString()}`); console.log(` Deadline: ${new Date(deadline * 1000).toISOString()}`);
// Build cast send command
const castCommand = `cast send ${PARTY_PLANNER_ADDRESS} \
"newPool(string,string,address[],int128,uint256[],uint256,bool,address,address,uint256[],uint256,uint256)" \
"${DEFAULT_POOL_PARAMS.name}" \
"${DEFAULT_POOL_PARAMS.symbol}" \
"[${tokenAddresses.join(',')}]" \
${DEFAULT_POOL_PARAMS.kappa.toString()} \
"[${DEFAULT_POOL_PARAMS.swapFeesPpm.join(',')}]" \
${DEFAULT_POOL_PARAMS.flashFeePpm} \
${DEFAULT_POOL_PARAMS.stable} \
${wallet.address} \
${RECEIVER_ADDRESS} \
"[${initialDeposits.join(',')}]" \
${DEFAULT_POOL_PARAMS.initialLpAmount.toString()} \
${deadline} \
--rpc-url ${RPC_URL} \
--private-key ${PRIVATE_KEY}`;
console.log(`\n[~] Cast command:\n${castCommand}\n`);
try { try {
const tx = await partyPlanner.newPool( // Execute cast command
DEFAULT_POOL_PARAMS.name, const { execSync } = await import('child_process');
DEFAULT_POOL_PARAMS.symbol, const output = execSync(castCommand, { encoding: 'utf-8' });
tokenAddresses,
DEFAULT_POOL_PARAMS.kappa,
DEFAULT_POOL_PARAMS.swapFeePpm,
DEFAULT_POOL_PARAMS.flashFeePpm,
DEFAULT_POOL_PARAMS.stable,
wallet.address, // payer (account #4)
RECEIVER_ADDRESS, // receiver (account #7)
initialDeposits,
DEFAULT_POOL_PARAMS.initialLpAmount,
deadline,
);
console.log(`[~] Transaction submitted: ${tx.hash}`);
console.log(`[~] Waiting for confirmation...`);
const receipt = await tx.wait();
console.log(`[+] Pool created successfully!`); console.log(`[+] Pool created successfully!`);
console.log(` Transaction: ${receipt.transactionHash}`); console.log(output);
console.log(` Block: ${receipt.blockNumber}`);
console.log(` Gas used: ${receipt.gasUsed.toString()}`);
// Try to extract pool address from events return output;
if (receipt.events && receipt.events.length > 0) {
const partyStartedEvent = receipt.events.find(e => e.event === 'PartyStarted');
if (partyStartedEvent && partyStartedEvent.args) {
console.log(` Pool address: ${partyStartedEvent.args.pool}`);
}
}
return receipt;
} catch (error) { } catch (error) {
console.error(`[!] Failed to create pool:`, error.message); console.error(`[!] Failed to create pool:`, error.message);
if (error.stderr) {
// Try to extract revert reason if available console.error(` Error output: ${error.stderr.toString()}`);
if (error.error && error.error.message) {
console.error(` Revert reason: ${error.error.message}`);
} }
throw error; throw error;
} }
} }
@@ -347,9 +339,9 @@ async function main() {
// Step 2: Calculate token amounts // Step 2: Calculate token amounts
const tokenAmounts = calculateTokenAmounts(prices, usdAmount); const tokenAmounts = calculateTokenAmounts(prices, usdAmount);
// Step 3: Connect to Anvil // Step 3: Connect to wallet
console.log(`\n[~] Connecting to Anvil at ${ANVIL_RPC_URL}...`); console.log(`\n[~] Connecting to test wallet at ${RPC_URL}...`);
const provider = new ethers.providers.JsonRpcProvider(ANVIL_RPC_URL); const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider); const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
console.log(`[+] Connected. Using wallet: ${wallet.address}`); console.log(`[+] Connected. Using wallet: ${wallet.address}`);