import { expect, test, type APIRequestContext } from '@playwright/test'; import { Wallet } from 'ethers'; import { createWalletContext } from '../setup/wallet-provider'; import { startStack, waitForStackReady, stopStack } from '../setup/stack'; const ACCOUNT_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; const ACCOUNT_ADDRESS = new Wallet(ACCOUNT_PRIVATE_KEY).address.toLowerCase(); const STACK_RPC_URL = process.env.STACK_RPC_URL ?? 'http://127.0.0.1:8545'; const STACK_WEBAPP_URL = process.env.STACK_WEBAPP_URL ?? 'http://localhost:5173'; const STACK_GRAPHQL_URL = process.env.STACK_GRAPHQL_URL ?? 'http://localhost:42069/graphql'; async function fetchPositions(request: APIRequestContext, owner: string) { const response = await request.post(STACK_GRAPHQL_URL, { data: { query: ` query PositionsByOwner($owner: String!) { positionss(where: { owner: $owner }, limit: 5) { items { id owner taxRate stakeDeposit status } } } `, variables: { owner }, }, headers: { 'content-type': 'application/json' }, }); expect(response.ok()).toBeTruthy(); const payload = await response.json(); return (payload?.data?.positionss?.items ?? []) as Array<{ id: string; owner: string; taxRate: number; stakeDeposit: string; status: string; }>; } test.describe('Acquire & Stake', () => { test.beforeAll(async () => { await startStack(); await waitForStackReady({ rpcUrl: STACK_RPC_URL, webAppUrl: STACK_WEBAPP_URL, graphqlUrl: STACK_GRAPHQL_URL, }); }); test.afterAll(async () => { await stopStack(); }); test('users can swap KRK via UI', async ({ browser, request }) => { console.log('[TEST] Creating wallet context...'); const context = await createWalletContext(browser, { privateKey: ACCOUNT_PRIVATE_KEY, rpcUrl: STACK_RPC_URL, }); const page = await context.newPage(); // Log browser console messages page.on('console', msg => console.log(`[BROWSER] ${msg.type()}: ${msg.text()}`)); page.on('pageerror', error => console.log(`[BROWSER ERROR] ${error.message}`)); try { console.log('[TEST] Loading app...'); await page.goto(`${STACK_WEBAPP_URL}/app/`, { waitUntil: 'domcontentloaded' }); console.log('[TEST] App loaded, waiting for wallet to initialize...'); // Wait for wallet to be fully recognized await page.waitForTimeout(3_000); // Check if wallet shows as connected in UI console.log('[TEST] Checking for wallet display...'); const walletDisplay = page.getByText(/0xf39F/i).first(); await expect(walletDisplay).toBeVisible({ timeout: 15_000 }); console.log('[TEST] Wallet connected successfully!'); console.log('[TEST] Navigating to cheats page...'); await page.goto(`${STACK_WEBAPP_URL}/app/#/cheats`); await expect(page.getByRole('heading', { name: 'Cheat Console' })).toBeVisible(); console.log('[TEST] Minting test ETH...'); await page.getByLabel('RPC URL').fill(STACK_RPC_URL); await page.getByLabel('Recipient').fill(ACCOUNT_ADDRESS); const mintButton = page.getByRole('button', { name: 'Mint' }); await expect(mintButton).toBeEnabled(); await mintButton.click(); await page.waitForTimeout(3_000); console.log('[TEST] Buying KRK tokens via swap...'); await page.screenshot({ path: 'test-results/before-swap.png' }); // Check if swap is available const buyWarning = await page.getByText('Connect to the Base Sepolia fork').isVisible().catch(() => false); if (buyWarning) { throw new Error('Swap not available - chain config issue persists'); } const ethToSpendInput = page.getByLabel('ETH to spend'); await ethToSpendInput.fill('0.05'); const buyButton = page.getByRole('button', { name: 'Buy' }).last(); await expect(buyButton).toBeVisible(); console.log('[TEST] Clicking Buy button...'); await buyButton.click(); // Wait for button to show "Submitting..." then return to "Buy" console.log('[TEST] Waiting for swap to process...'); try { await page.getByRole('button', { name: /Submitting/i }).waitFor({ state: 'visible', timeout: 5_000 }); console.log('[TEST] Swap initiated, waiting for completion...'); await page.getByRole('button', { name: 'Buy' }).last().waitFor({ state: 'visible', timeout: 60_000 }); console.log('[TEST] Swap completed!'); } catch (e) { console.log('[TEST] No "Submitting" state detected, swap may have completed instantly'); } await page.waitForTimeout(2_000); console.log('[TEST] Verifying swap via RPC...'); // Query the blockchain directly to verify KRK balance increased const balanceResponse = await fetch(STACK_RPC_URL, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_call', params: [{ to: '0xe527ddac2592faa45884a0b78e4d377a5d3df8cc', // KRK token data: `0x70a08231000000000000000000000000${ACCOUNT_ADDRESS.slice(2)}` // balanceOf(address) }, 'latest'] }) }); const balanceData = await balanceResponse.json(); const balance = BigInt(balanceData.result || '0'); console.log(`[TEST] KRK balance: ${balance.toString()} wei`); expect(balance).toBeGreaterThan(0n); console.log('[TEST] ✅ Swap successful! KRK balance > 0'); console.log('[TEST] ✅ E2E test complete: Swap verified through UI'); console.log('[TEST] Note: Staking is verified separately via verify-swap.sh script'); } finally { await context.close(); } }); });