-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* setup vitest with anvil * get op stack and non-op chains running * fixes * bork * example env file * fund wallet with USDC * passing * simplify execute quote file, clean up * fill as relayer, check fill receipt * clean up * run tests in CI * update example env file * remove duplicate across client instance * let echo create the env file Co-authored-by: Paul <[email protected]> * make prool dev dependency * remove unused op stack anvil chains * reset forks after each test file * add comment about exposed private key * use latestblock * don't mock api * remove log --------- Co-authored-by: Paul <[email protected]>
- Loading branch information
1 parent
0b09340
commit a728b6b
Showing
31 changed files
with
8,882 additions
and
11,008 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VITE_ANVIL_ALCHEMY_KEY="<key>" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
export type MakeOptional<T extends object, K extends keyof T> = Omit<T, K> & | ||
Partial<Pick<T, K>>; | ||
|
||
export type NoNullValuesOfObject<T extends object> = { | ||
[Property in keyof T]-?: NonNullable<T[Property]>; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
import { arbitrum, type Chain, mainnet } from "viem/chains"; | ||
import { | ||
BLOCK_NUMBER_ARBITRUM, | ||
BLOCK_NUMBER_MAINNET, | ||
FORK_URL_ARBITRUM, | ||
FORK_URL_MAINNET, | ||
pool, | ||
PRIVATE_KEY, | ||
} from "./constants"; | ||
import { | ||
type Account, | ||
type Client, | ||
createPublicClient, | ||
createTestClient, | ||
createWalletClient, | ||
http, | ||
publicActions, | ||
type PublicActions, | ||
type TestActions, | ||
type TestRpcSchema, | ||
type Transport, | ||
type WalletActions, | ||
walletActions, | ||
} from "viem"; | ||
import { privateKeyToAccount } from "viem/accounts"; | ||
import { type Compute } from "./utils"; | ||
import { createServer } from "prool"; | ||
import { anvil } from "prool/instances"; | ||
|
||
export function getRpcUrls({ port }: { port: number }) { | ||
return { | ||
port, | ||
rpcUrls: { | ||
default: { | ||
// append the test worker id to the rpc urls. | ||
http: [`http://localhost:${port}/${pool}`], | ||
webSocket: [`ws://localhost:${port}/${pool}`], | ||
}, | ||
public: { | ||
http: [`http://localhost:${port}/${pool}`], | ||
webSocket: [`ws://localhost:${port}/${pool}`], | ||
}, | ||
}, | ||
} as const; | ||
} | ||
|
||
type Fork = { blockNumber: bigint; url: string; opStack?: boolean }; | ||
|
||
export type AnvilChain = Compute< | ||
Chain & { | ||
fork: Fork; | ||
port: number; | ||
} | ||
>; | ||
|
||
const mainnetFork = { | ||
blockNumber: BLOCK_NUMBER_MAINNET, | ||
url: FORK_URL_MAINNET, | ||
} as const satisfies Fork; | ||
|
||
const arbitrumFork = { | ||
blockNumber: BLOCK_NUMBER_ARBITRUM, | ||
url: FORK_URL_ARBITRUM, | ||
} as const satisfies Fork; | ||
|
||
// PORT: 8547 | ||
const mainnetAnvil = { | ||
...mainnet, | ||
...getRpcUrls({ port: 8547 }), | ||
fork: mainnetFork, | ||
} as const satisfies AnvilChain; | ||
|
||
// PORT: 8548 | ||
const arbitrumAnvil = { | ||
...arbitrum, | ||
...getRpcUrls({ port: 8548 }), | ||
fork: arbitrumFork, | ||
} as const satisfies AnvilChain; | ||
|
||
const account = privateKeyToAccount(PRIVATE_KEY); | ||
|
||
// TEST (CHAIN) CLIENTS | ||
export const chainClientMainnet: ChainClient = createTestClient({ | ||
account, | ||
chain: mainnetAnvil, | ||
mode: "anvil", | ||
transport: http(), | ||
}) | ||
.extend(forkMethods) | ||
.extend(publicActions) | ||
.extend(walletActions); | ||
|
||
export const chainClientArbitrum: ChainClient = createTestClient({ | ||
account, | ||
chain: arbitrumAnvil, | ||
mode: "anvil", | ||
transport: http(), | ||
}) | ||
.extend(forkMethods) | ||
.extend(publicActions) | ||
.extend(walletActions); | ||
|
||
// PUBLIC CLIENTS | ||
export const publicClientMainnet = createPublicClient({ | ||
chain: mainnetAnvil, | ||
transport: http(), | ||
}); | ||
|
||
export const publicClientArbitrum = createPublicClient({ | ||
chain: arbitrumAnvil, | ||
transport: http(), | ||
}); | ||
|
||
// WALLET CLIENTS | ||
export const testWalletMainnet = createWalletClient({ | ||
account, | ||
chain: mainnetAnvil, | ||
transport: http(), | ||
}); | ||
|
||
export const testWalletArbitrum = createWalletClient({ | ||
account, | ||
chain: arbitrumAnvil, | ||
transport: http(), | ||
}); | ||
|
||
export type ChainClient = Client< | ||
Transport, | ||
AnvilChain, | ||
Account, | ||
TestRpcSchema<"anvil">, | ||
TestActions & ForkMethods & PublicActions & WalletActions | ||
>; | ||
|
||
type ForkMethods = ReturnType<typeof forkMethods>; | ||
|
||
function forkMethods( | ||
client: Client< | ||
Transport, | ||
AnvilChain, | ||
Account, | ||
TestRpcSchema<"anvil">, | ||
TestActions | ||
>, | ||
) { | ||
return { | ||
async restart() { | ||
return await fetch(`${client.chain.rpcUrls.default.http[0]}/restart`); | ||
}, | ||
async stop() { | ||
return await fetch(`${client.chain.rpcUrls.default.http[0]}/stop`); | ||
}, | ||
async healthcheck() { | ||
return await fetch(`${client.chain.rpcUrls.default.http[0]}/healthcheck`); | ||
}, | ||
async start() { | ||
const server = createServer({ | ||
instance: anvil({ | ||
chainId: client.chain.id, | ||
forkUrl: client.chain.fork.url, | ||
forkBlockNumber: client.chain.fork.blockNumber, | ||
blockTime: 1, | ||
}), | ||
port: client.chain.port, | ||
}); | ||
|
||
await server.start(); | ||
|
||
const res = await this.healthcheck(); | ||
console.log(res); | ||
return server; | ||
}, | ||
/** Resets fork attached to chain at starting block number. */ | ||
resetFork() { | ||
return client.reset({ | ||
jsonRpcUrl: client.chain.fork.url, | ||
blockNumber: client.chain.fork.blockNumber, | ||
}); | ||
}, | ||
}; | ||
} | ||
|
||
export const chains = { | ||
arbitrumAnvil, | ||
mainnetAnvil, | ||
}; | ||
|
||
export const chainClients: Record<string, ChainClient> = { | ||
chainClientMainnet, | ||
chainClientArbitrum, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { getAddress } from "viem"; | ||
|
||
export const pool = Number(process.env.VITEST_POOL_ID ?? 1); | ||
|
||
// Test accounts | ||
export const ACCOUNTS = [ | ||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", | ||
"0x70997970c51812dc3a010c7d01b50e0d17dc79c8", | ||
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", | ||
"0x90F79bf6EB2c4f870365E785982E1f101E93b906", | ||
"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", | ||
"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", | ||
"0x976EA74026E726554dB657fA54763abd0C3a0aa9", | ||
"0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", | ||
"0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", | ||
"0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", | ||
] as const; | ||
|
||
// Intentionally disclosed private key for 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 | ||
export const PRIVATE_KEY = | ||
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; | ||
|
||
// Named accounts | ||
export const [ALICE, BOB, RELAYER] = ACCOUNTS; | ||
|
||
export const USDC_MAINNET = getAddress( | ||
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", | ||
); | ||
export const USDC_WHALE = getAddress( | ||
"0x55fe002aeff02f77364de339a1292923a15844b8", | ||
); | ||
|
||
function getEnv(key: string): string { | ||
if (!process.env[key]) { | ||
throw new Error(`Missing environment variable "${key}"`); | ||
} | ||
return process.env[key]; | ||
} | ||
|
||
function getMaybeEnv(key: string): string | undefined { | ||
return process.env[key]; | ||
} | ||
const ALCHEMY_KEY = getEnv("VITE_ANVIL_ALCHEMY_KEY"); | ||
// FORK URLs | ||
export const FORK_URL_OPTIMISM = `https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`; | ||
export const FORK_URL_BASE = `https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`; | ||
export const FORK_URL_MAINNET = `https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`; | ||
export const FORK_URL_ARBITRUM = `https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`; | ||
|
||
// FORK BLOCK NUMBERS | ||
export const BLOCK_NUMBER_OPTIMISM = BigInt(126951625); | ||
export const BLOCK_NUMBER_BASE = BigInt(21363706); | ||
export const BLOCK_NUMBER_MAINNET = BigInt(21020558); | ||
export const BLOCK_NUMBER_ARBITRUM = BigInt(266447962); | ||
|
||
export const TENDERLY_KEY = getMaybeEnv("VITE_TENDERLY_KEY"); | ||
export const MOCK_API = getMaybeEnv("VITE_MOCK_API") === "true"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { chainClients } from "./anvil"; | ||
|
||
export default async function () { | ||
const servers = await Promise.all( | ||
Object.values(chainClients).map((chain) => chain.start()), | ||
); | ||
|
||
return async () => { | ||
await Promise.all(servers.map((chain) => chain.stop())); | ||
}; | ||
} |
Oops, something went wrong.