Skip to content

Files

Latest commit

 

History

History
371 lines (316 loc) · 39.3 KB

File metadata and controls

371 lines (316 loc) · 39.3 KB

Test Examples

OlympusDAO

This is one of the simpler examples. It stakes OHM to gOHM and doesn't require any complex mocking beyond what is easily accessible via the GUI API.

import { test } from "@framework/test";

test.describe("Olympus", () => {
    test("Should stake OHM to gOHM", async ({ page, gui }) => {
        // Navigate to site
        await page.goto("https://app.olympusdao.finance/#/stake");

        // Mocking
        await gui.setEthBalance("100000000000000000000000");
        await gui.setAllowance("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", "0xb63cac384247597756545b500253ff8e607a8020", "1000000000000000000000000");
        await gui.setBalance("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", "1000000000000000000000000");


        // Clear any info modals
        let infoModalIsVisible = await page.isVisible("text=Did You Know?");
        if (infoModalIsVisible) {
            await page.locator("[id='root']").click({ position: {x: 0, y: 0}, force: true });
        }

        await page.waitForSelector("text=Connect Wallet");
        await page.locator("text=Connect Wallet").first().click();
        await page.waitForSelector("text=Connect Wallet");
        await page.locator("text=Connect Wallet").first().click();
        await page.locator("text=Metamask").first().click();
        await page.locator("[id='root']").click({ position: {x: 0, y: 0}, force: true });

        // Enter OHM input amount
        await page.locator("[data-testid='ohm-input']").type("0.1");

        // Execute stake
        await page.waitForSelector("[data-testid='submit-button']");
        await page.locator("[data-testid='submit-button']").click();

        // Sign checkbox transaction
        await page.waitForSelector("[class='PrivateSwitchBase-input css-1m9pwf3']");
        await page.locator("[class='PrivateSwitchBase-input css-1m9pwf3']").click();

        // Submit stake transaction
        await gui.validateContractInteraction("[data-testid='submit-modal-button']", "0xb63cac384247597756545b500253ff8e607a8020");
    });
});

Bond Protocol (Subgraph Mocking)

This is an example from Bond Protocol where we have to pin the block and mock their Subgraph to make sure that the site propagates the correct market we want to interact with.

import { test } from "@framework/test";

test.describe("Bond Protocol Demo", () => {
    test("Should use Bond Protocol's app", async ({ page, gui }) => {
        // Set up markets mocking
          const isBondSubgraphUrl = (url: URL) => {
                if (url.hostname === "gateway.thegraph.com" || url.hostname === "api.thegraph.com") {
                    return true;
                }
    
                return false;
            };
        
        page.route(isBondSubgraphUrl, async (route, request) => {
            if (request.method() === "POST") {
                const postData = JSON.parse(request.postData() as string);

                if (postData.query.includes("query ListMarkets")) {
                    const resultData = {
                        "data": {
                            "markets": [
                                {
                                    "id": "1_BondFixedTermCDA_93",
                                    "name": "BondFixedTermCDA",
                                    "network": "mainnet",
                                    "auctioneer": "0x007f7a1cb838a872515c8ebd16be4b14ef43a222",
                                    "teller": "0x007f7735baf391e207e3aa380bb53c4bd9a5fed6",
                                    "marketId": "93",
                                    "owner": "0x1ce568dbb34b2631acdb5b453c3195ea0070ec65",
                                    "callbackAddress": "0xbf2b6e99b0e8d4c96b946c182132f5752eaa55c6",
                                    "capacity": "3007946952824079301902603",
                                    "capacityInQuote": false,
                                    "chainId": "1",
                                    "minPrice": "9550186228631458300000000000000000",
                                    "scale": "100000000000000000000000000000000000000000000",
                                    "start": null,
                                    "conclusion": "1682501315",
                                    "payoutToken": {
                                        "id": "1_0x6b175474e89094c44da98b954eedeac495271d0f",
                                        "address": "0x6b175474e89094c44da98b954eedeac495271d0f",
                                        "symbol": "DAI",
                                        "decimals": "18",
                                        "name": "Dai Stablecoin"
                                    },
                                    "quoteToken": {
                                        "id": "1_0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
                                        "address": "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
                                        "symbol": "OHM",
                                        "decimals": "9",
                                        "name": "Olympus",
                                        "lpPair": null,
                                        "balancerWeightedPool": null
                                    },
                                    "vesting": "0",
                                    "vestingType": "fixed-term",
                                    "isInstantSwap": true,
                                    "hasClosed": false,
                                    "totalBondedAmount": "30027.135451676",
                                    "totalPayoutAmount": "314192.45789798277",
                                    "creationBlockTimestamp": "1682242115"
                                },
                            ]
                        }
                    };
    
                    route.fulfill({
                        contentType: "application/json",
                        body: JSON.stringify(resultData)
                    });
                } else {
                    route.continue();
                }
            } else {
                route.continue();
            }
        });

        // Initialize fork
        await gui.initializeChain(1, 17110784);

        // Go to bond protocol
        await page.goto("https://app.bondprotocol.finance/#/markets");

        // Mocking
        await gui.initializeWallet(1);
        await gui.setEthBalance("100000000000000000000000");
        await gui.setAllowance("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", "0x007f7735baf391e207e3aa380bb53c4bd9a5fed6", "1000000000000000000000000");
        await gui.setBalance("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", "1000000000000000000000000");

        await page.waitForSelector("tbody > tr");
        await page.locator("tbody > tr >> nth=0").click();

        await page.waitForSelector("input[placeholder='Enter Amount to Bond']");
        await page.locator("input[placeholder='Enter Amount to Bond']").first().fill("10");

        await page.waitForSelector("button:has-text('BOND')");
        await page.locator("button:has-text('BOND')").first().click();

        await gui.validateContractInteraction("button:has-text('CONFIRM BOND')", "0x007f7735baf391e207e3aa380bb53c4bd9a5fed6");

        await page.waitForSelector("text=Thanks for bonding at OlympusDAO");

        await gui.killChain();
    });
});

Bond Protocol (Complex Chain Interactions)

This is a more complicated example from Bond Protocol where we first have to mimic the existence of a Fixed Expiry market on-chain since none have been actually spun up at the time of writing the test.

import { test } from "@framework/test";
import { Page } from "@playwright/test";
import { ethers } from "ethers";
import { findAllowanceSlot, findBalanceSlot, getAllowanceSlot, getBalanceSlot } from "../framework/utils";

// Needs block 17110784

const fixedExpiryTellerAbi = [{"inputs":[{"internalType":"address","name":"protocol_","type":"address"},{"internalType":"contract IBondAggregator","name":"aggregator_","type":"address"},{"internalType":"address","name":"guardian_","type":"address"},{"internalType":"contract Authority","name":"authority_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreateFail","type":"error"},{"inputs":[],"name":"Teller_InvalidCallback","type":"error"},{"inputs":[],"name":"Teller_InvalidParams","type":"error"},{"inputs":[],"name":"Teller_NotAuthorized","type":"error"},{"inputs":[{"internalType":"contract ERC20","name":"underlying","type":"address"},{"internalType":"uint48","name":"expiry","type":"uint48"}],"name":"Teller_TokenDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint48","name":"maturesOn","type":"uint48"}],"name":"Teller_TokenNotMatured","type":"error"},{"inputs":[],"name":"Teller_UnsupportedToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"}],"name":"Bonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ERC20BondToken","name":"bondToken","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"underlying","type":"address"},{"indexed":true,"internalType":"uint48","name":"expiry","type":"uint48"}],"name":"ERC20BondTokenCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"inputs":[],"name":"FEE_DECIMALS","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondTokenImplementation","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"","type":"address"},{"internalType":"uint48","name":"","type":"uint48"}],"name":"bondTokens","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20[]","name":"tokens_","type":"address[]"},{"internalType":"address","name":"to_","type":"address"}],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"underlying_","type":"address"},{"internalType":"uint48","name":"expiry_","type":"uint48"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"create","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createFeeDiscount","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"underlying_","type":"address"},{"internalType":"uint48","name":"expiry_","type":"uint48"}],"name":"deploy","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"underlying_","type":"address"},{"internalType":"uint48","name":"expiry_","type":"uint48"}],"name":"getBondToken","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"getBondTokenForMarket","outputs":[{"internalType":"contract ERC20BondToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer_","type":"address"}],"name":"getFee","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient_","type":"address"},{"internalType":"address","name":"referrer_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"minAmountOut_","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20BondToken","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrerFees","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract ERC20","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"discount_","type":"uint48"}],"name":"setCreateFeeDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"fee_","type":"uint48"}],"name":"setProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"fee_","type":"uint48"}],"name":"setReferrerFee","outputs":[],"stateMutability":"nonpayable","type":"function"}];
const fixedExpirySdaAbi = [{"inputs":[{"internalType":"contract IBondTeller","name":"teller_","type":"address"},{"internalType":"contract IBondAggregator","name":"aggregator_","type":"address"},{"internalType":"address","name":"guardian_","type":"address"},{"internalType":"contract Authority","name":"authority_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Auctioneer_AmountLessThanMinimum","type":"error"},{"inputs":[],"name":"Auctioneer_BadExpiry","type":"error"},{"inputs":[],"name":"Auctioneer_InitialPriceLessThanMin","type":"error"},{"inputs":[],"name":"Auctioneer_InvalidCallback","type":"error"},{"inputs":[],"name":"Auctioneer_InvalidParams","type":"error"},{"inputs":[{"internalType":"uint256","name":"conclusion_","type":"uint256"}],"name":"Auctioneer_MarketConcluded","type":"error"},{"inputs":[],"name":"Auctioneer_MaxPayoutExceeded","type":"error"},{"inputs":[],"name":"Auctioneer_NewMarketsNotAllowed","type":"error"},{"inputs":[],"name":"Auctioneer_NotAuthorized","type":"error"},{"inputs":[],"name":"Auctioneer_NotEnoughCapacity","type":"error"},{"inputs":[],"name":"Auctioneer_OnlyMarketOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"defaultTuneInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"defaultTuneAdjustment","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDebtDecayInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDepositInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minMarketDuration","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDebtBuffer","type":"uint32"}],"name":"DefaultsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"MarketClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"payoutToken","type":"address"},{"indexed":true,"internalType":"address","name":"quoteToken","type":"address"},{"indexed":false,"internalType":"uint48","name":"vesting","type":"uint48"},{"indexed":false,"internalType":"uint256","name":"initialPrice","type":"uint256"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldControlVariable","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newControlVariable","type":"uint256"}],"name":"Tuned","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"adjustments","outputs":[{"internalType":"uint256","name":"change","type":"uint256"},{"internalType":"uint48","name":"lastAdjustment","type":"uint48"},{"internalType":"uint48","name":"timeToAdjusted","type":"uint48"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowNewMarkets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"callbackAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"closeMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"params_","type":"bytes"}],"name":"createMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentControlVariable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultTuneAdjustment","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultTuneInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAggregator","outputs":[{"internalType":"contract IBondAggregator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"getMarketInfoForPurchase","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"callbackAddr","type":"address"},{"internalType":"contract ERC20","name":"payoutToken","type":"address"},{"internalType":"contract ERC20","name":"quoteToken","type":"address"},{"internalType":"uint48","name":"vesting","type":"uint48"},{"internalType":"uint256","name":"maxPayout","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTeller","outputs":[{"internalType":"contract IBondTeller","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"isInstantSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"isLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"marketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"marketScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract ERC20","name":"payoutToken","type":"address"},{"internalType":"contract ERC20","name":"quoteToken","type":"address"},{"internalType":"address","name":"callbackAddr","type":"address"},{"internalType":"bool","name":"capacityInQuote","type":"bool"},{"internalType":"uint256","name":"capacity","type":"uint256"},{"internalType":"uint256","name":"totalDebt","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"sold","type":"uint256"},{"internalType":"uint256","name":"purchased","type":"uint256"},{"internalType":"uint256","name":"scale","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"referrer_","type":"address"}],"name":"maxAmountAccepted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"metadata","outputs":[{"internalType":"uint48","name":"lastTune","type":"uint48"},{"internalType":"uint48","name":"lastDecay","type":"uint48"},{"internalType":"uint32","name":"length","type":"uint32"},{"internalType":"uint32","name":"depositInterval","type":"uint32"},{"internalType":"uint32","name":"tuneInterval","type":"uint32"},{"internalType":"uint32","name":"tuneAdjustmentDelay","type":"uint32"},{"internalType":"uint32","name":"debtDecayInterval","type":"uint32"},{"internalType":"uint256","name":"tuneIntervalCapacity","type":"uint256"},{"internalType":"uint256","name":"tuneBelowCapacity","type":"uint256"},{"internalType":"uint256","name":"lastTuneDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDebtBuffer","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDebtDecayInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDepositInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minMarketDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"newOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"referrer_","type":"address"}],"name":"payoutFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"pullOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"minAmountOut_","type":"uint256"}],"name":"purchaseBond","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"newOwner_","type":"address"}],"name":"pushOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status_","type":"bool"}],"name":"setAllowNewMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator_","type":"address"},{"internalType":"bool","name":"status_","type":"bool"}],"name":"setCallbackAuthStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[6]","name":"defaults_","type":"uint32[6]"}],"name":"setDefaults","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint32[3]","name":"intervals_","type":"uint32[3]"}],"name":"setIntervals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"terms","outputs":[{"internalType":"uint256","name":"controlVariable","type":"uint256"},{"internalType":"uint256","name":"maxDebt","type":"uint256"},{"internalType":"uint48","name":"vesting","type":"uint48"},{"internalType":"uint48","name":"conclusion","type":"uint48"}],"stateMutability":"view","type":"function"}];

const createMarket = async (page: Page) => {
    const provider = new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545", 1);

    // Impersonate Olympus Account
    await provider.send(
        "anvil_impersonateAccount",
        ["0x1ce568dbb34b2631acdb5b453c3195ea0070ec65"]
    );
    const signer = await provider.getSigner("0x1ce568dbb34b2631acdb5b453c3195ea0070ec65");

    const fixedExpiryTeller = new ethers.Contract("0x007FE70dc9797C4198528aE43d8195ffF82Bdc95", fixedExpiryTellerAbi, signer);
    const fixedExpirySDA = new ethers.Contract("0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD", fixedExpirySdaAbi, signer);

    // Set ETH balance
    const ethBn = ethers.utils.parseEther("1000");
    await provider.send(
        "anvil_setBalance",
        [
            "0x1ce568dbb34b2631acdb5b453c3195ea0070ec65",
            ethers.utils.hexlify(ethBn)
        ]
    );

    // Set OHM balance
    const balanceSlot = await findBalanceSlot("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", page);
    const userBalanceSlot = getBalanceSlot("0x1ce568dbb34b2631acdb5b453c3195ea0070ec65", balanceSlot);
    const bnAmount = ethers.BigNumber.from("100000000000000000");
    await provider.send(
        "anvil_setStorageAt",
        [
            "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
            userBalanceSlot,
            ethers.utils.hexZeroPad(ethers.utils.hexlify(bnAmount), 32)
        ]
    );

    // Set OHM allowance
    const allowanceSlot = await findAllowanceSlot("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", page);
    const tellerAllowanceSlot = getAllowanceSlot("0x1ce568dbb34b2631acdb5b453c3195ea0070ec65", "0x007FE70dc9797C4198528aE43d8195ffF82Bdc95", allowanceSlot);
    const sdaAllowanceSlot = getAllowanceSlot("0x1ce568dbb34b2631acdb5b453c3195ea0070ec65", "0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD", allowanceSlot);
    await provider.send(
        "anvil_setStorageAt",
        [
            "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
            tellerAllowanceSlot,
            ethers.utils.hexZeroPad(ethers.utils.hexlify(bnAmount), 32)
        ]
    );
    await provider.send(
        "anvil_setStorageAt",
        [
            "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
            sdaAllowanceSlot,
            ethers.utils.hexZeroPad(ethers.utils.hexlify(bnAmount), 32)
        ]
    );

    // Create 1 day bond token
    const bondTokenTx = await fixedExpiryTeller.deploy("0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5", "1702425600");
    await bondTokenTx.wait();

    // Create SDA market
    const abiCoder = new ethers.utils.AbiCoder();
    const params = abiCoder.encode(
        ["address", "address", "address", "bool", "uint256", "uint256",
    "uint256", "uint32", "uint48", "uint48", "uint32", "int8"],
        [
            "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
            "0x6b175474e89094c44da98b954eedeac495271d0f",
            "0x0000000000000000000000000000000000000000",
            false,
            "100000000000000000",
            "1000000000000000000000000000000000000",
            "500000000000000000000000000000000000",
            "100000",
            "1702425600",
            "1692242115",
            "21600",
            "0"
        ]
    );
    const sdaMarketTx = await fixedExpirySDA.createMarket(params);
    await sdaMarketTx.wait();

    // Stop impersonating Olympus Account
    await provider.send(
        "anvil_stopImpersonatingAccount",
        ["0x1ce568dbb34b2631acdb5b453c3195ea0070ec65"]
    );
};

test.describe("Bond Protocol", () => {
    test("Should approve fixed expiry teller", async ({ page, gui }) => {
        // Mock subgraph
        const isBondSubgraphUrl = (url: URL) => {
            if (url.hostname === "gateway.thegraph.com" || url.hostname === "api.thegraph.com") {
                return true;
            }

            return false;
        };
        
        page.route(isBondSubgraphUrl, async (route, request) => {
            if (request.method() === "POST") {
                const postData = JSON.parse(request.postData() as string);

                if (postData.query.includes("query ListMarkets")) {
                    const resultData = {
                        "data": {
                            "markets": [
                                {
                                    "id": "1_BondFixedExpCDA_94",
                                    "name": "BondFixedExpCDA",
                                    "network": "mainnet",
                                    "auctioneer": "0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD",
                                    "teller": "0x007FE70dc9797C4198528aE43d8195ffF82Bdc95",
                                    "marketId": "94",
                                    "owner": "0x1ce568dbb34b2631acdb5b453c3195ea0070ec65",
                                    "callbackAddress": "0x0000000000000000000000000000000000000000",
                                    "capacity": "100000000000000000",
                                    "capacityInQuote": false,
                                    "chainId": "1",
                                    "minPrice": "500000000000000000000000000000000000",
                                    "scale": "100000000000000000000000000000000000000000000",
                                    "start": null,
                                    "conclusion": "1692242115",
                                    "payoutToken": {
                                        "id": "1_0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
                                        "address": "0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5",
                                        "symbol": "OHM",
                                        "decimals": "9",
                                        "name": "Olympus"
                                    },
                                    "quoteToken": {
                                        "id": "1_0x6b175474e89094c44da98b954eedeac495271d0f",
                                        "address": "0x6b175474e89094c44da98b954eedeac495271d0f",
                                        "symbol": "DAI",
                                        "decimals": "18",
                                        "name": "DAI Stablecoin",
                                        "lpPair": null,
                                        "balancerWeightedPool": null
                                    },
                                    "vesting": "1702425600",
                                    "vestingType": "fixed-exp",
                                    "isInstantSwap": false,
                                    "hasClosed": false,
                                    "totalBondedAmount": "0",
                                    "totalPayoutAmount": "0",
                                    "creationBlockTimestamp": "1682245571"
                                },
                            ]
                        }
                    };
    
                    route.fulfill({
                        contentType: "application/json",
                        body: JSON.stringify(resultData)
                    });
                } else if (postData.query.includes("query ListTokens")) {
                    const resultData ={"data":{"tokens":[{"id":"1_0x2c5bc2ba3614fd27fcc7022ea71d9172e2632c16","network":"mainnet","chainId":"1","address":"0x2c5bc2ba3614fd27fcc7022ea71d9172e2632c16","decimals":"18","symbol":"SOV","name":"ShibOriginalVision","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68","network":"mainnet","chainId":"1","address":"0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68","decimals":"18","symbol":"INV","name":"Inverse DAO","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b","network":"mainnet","chainId":"1","address":"0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b","decimals":"18","symbol":"CVX","name":"Convex Token","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x569424c5ee13884a193773fdc5d1c5f79c443a51","network":"mainnet","chainId":"1","address":"0x569424c5ee13884a193773fdc5d1c5f79c443a51","decimals":"18","symbol":"PINE","name":"Pine Token","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x579cea1889991f68acc35ff5c3dd0621ff29b0c9","network":"mainnet","chainId":"1","address":"0x579cea1889991f68acc35ff5c3dd0621ff29b0c9","decimals":"18","symbol":"IQ","name":"Everipedia IQ","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x5f98805a4e8be255a32880fdec7f6728c6568ba0","network":"mainnet","chainId":"1","address":"0x5f98805a4e8be255a32880fdec7f6728c6568ba0","decimals":"18","symbol":"LUSD","name":"LUSD Stablecoin","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5","network":"mainnet","chainId":"1","address":"0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5","decimals":"9","symbol":"OHM","name":"Olympus","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x6b175474e89094c44da98b954eedeac495271d0f","network":"mainnet","chainId":"1","address":"0x6b175474e89094c44da98b954eedeac495271d0f","decimals":"18","symbol":"DAI","name":"Dai Stablecoin","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x865377367054516e17014ccded1e7d814edc9ce4","network":"mainnet","chainId":"1","address":"0x865377367054516e17014ccded1e7d814edc9ce4","decimals":"18","symbol":"DOLA","name":"Dola USD Stablecoin","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce","network":"mainnet","chainId":"1","address":"0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce","decimals":"18","symbol":"SHIB","name":"SHIBA INU","lpPair":null,"balancerWeightedPool":null},{"id":"1_0x98585dfc8d9e7d48f0b1ae47ce33332cf4237d96","network":"mainnet","chainId":"1","address":"0x98585dfc8d9e7d48f0b1ae47ce33332cf4237d96","decimals":"18","symbol":"NEWO","name":"New Order","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","network":"mainnet","chainId":"1","address":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","decimals":"6","symbol":"USDC","name":"USD Coin","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","network":"mainnet","chainId":"1","address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","decimals":"18","symbol":"WETH","name":"Wrapped Ether","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xc08ed9a9abeabcc53875787573dc32eee5e43513","network":"mainnet","chainId":"1","address":"0xc08ed9a9abeabcc53875787573dc32eee5e43513","decimals":"18","symbol":"SLP","name":"SushiSwap LP Token","lpPair":{"token0":{"id":"1_0x98585dfc8d9e7d48f0b1ae47ce33332cf4237d96"},"token1":{"id":"1_0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"}},"balancerWeightedPool":null},{"id":"1_0xc55126051b22ebb829d00368f4b12bde432de5da","network":"mainnet","chainId":"1","address":"0xc55126051b22ebb829d00368f4b12bde432de5da","decimals":"18","symbol":"BTRFLY","name":"BTRFLY","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xc770eefad204b5180df6a14ee197d99d808ee52d","network":"mainnet","chainId":"1","address":"0xc770eefad204b5180df6a14ee197d99d808ee52d","decimals":"18","symbol":"FOX","name":"FOX","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xdac17f958d2ee523a2206206994597c13d831ec7","network":"mainnet","chainId":"1","address":"0xdac17f958d2ee523a2206206994597c13d831ec7","decimals":"6","symbol":"USDT","name":"Tether USD","lpPair":null,"balancerWeightedPool":null},{"id":"1_0xe80c0cd204d654cebe8dd64a4857cab6be8345a3","network":"mainnet","chainId":"1","address":"0xe80c0cd204d654cebe8dd64a4857cab6be8345a3","decimals":"18","symbol":"JPEG","name":"JPEG’d Governance Token","lpPair":null,"balancerWeightedPool":null}]}};

                    route.fulfill({
                        contentType: "application/json",
                        body: JSON.stringify(resultData)
                    });
                } else {
                    route.continue();
                }
            } else {
                route.continue();
            }
        });

        // Go to bond protocol
        await page.goto("https://app.bondprotocol.finance/#/markets");

        // Create market
        await createMarket(page);

        // Mocking
        await gui.setEthBalance("100000000000000000000000");
        await gui.setBalance("0x6b175474e89094c44da98b954eedeac495271d0f", "1000000000000000000000000");

        // No allowance yet

        await page.waitForSelector("tbody > tr");
        await page.locator("tbody > tr >> nth=0").click();

        // Verify that approval uses the correct contract
        await page.waitForSelector("button:has-text('APPROVE')");
        await gui.validateContractInteraction("button:has-text('APPROVE')", "0x007FE70dc9797C4198528aE43d8195ffF82Bdc95");
    });
});