From ab638e05189af0911b19296bced16e442e31c05a Mon Sep 17 00:00:00 2001 From: Jamie Harding Date: Mon, 30 Sep 2024 14:30:03 +0200 Subject: [PATCH] format --- .../[strategyName]/[deployment]/page.tsx | 121 +- app/[projectName]/[strategyName]/page.tsx | 72 +- app/_components/FrameImage.tsx | 36 +- app/_components/ShareStateAsUrl.tsx | 72 +- app/_components/StrategyAnalytics.tsx | 3 +- app/_components/SubmissionModal.tsx | 21 +- app/_components/TradesTable.tsx | 6 +- app/_components/WebappFrame.tsx | 6 +- app/_components/WithdrawalModal.tsx | 3 +- app/_queries/subgraphs.tsx | 10 +- app/_schemas/failsafeWithNumbers.ts | 20 +- app/_services/buildProjectHome.tsx | 95 +- app/_services/dates.ts | 8 +- app/_services/frameButtons.tsx | 9 +- app/_services/frameTransactions.ts | 158 +- app/_services/parseDotrainFrontmatter.tsx | 55 +- app/_services/tokenApproval.ts | 64 +- app/_services/transactionData.ts | 104 +- app/_types/yamlData.ts | 106 +- app/my-strategies/[transactionId]/page.tsx | 10 +- app/my-strategies/page.tsx | 3 +- components/ui/button.tsx | 91 +- components/ui/dialog.tsx | 3 +- components/ui/form.tsx | 273 +- components/ui/label.tsx | 31 +- package.json | 2 +- postcss.config.js | 10 +- public/_abis/OrderBook.ts | 7851 ++++++++--------- public/_strategies/arbitrum/webapp.md | 2 +- 29 files changed, 4559 insertions(+), 4686 deletions(-) diff --git a/app/[projectName]/[strategyName]/[deployment]/page.tsx b/app/[projectName]/[strategyName]/[deployment]/page.tsx index f6a3c75b..6f7535b7 100644 --- a/app/[projectName]/[strategyName]/[deployment]/page.tsx +++ b/app/[projectName]/[strategyName]/[deployment]/page.tsx @@ -1,82 +1,73 @@ -import { fetchMetadata } from "frames.js/next"; -import { Metadata } from "next"; -import WebappFrame from "@/app/_components/WebappFrame"; -import fs from "fs"; -import path from "path"; +import { fetchMetadata } from 'frames.js/next'; +import { Metadata } from 'next'; +import WebappFrame from '@/app/_components/WebappFrame'; +import fs from 'fs'; +import path from 'path'; interface generateMetadataProps { - params: { - projectName: string; - strategyName: string; - deployment: string; - }; + params: { + projectName: string; + strategyName: string; + deployment: string; + }; } -export async function generateMetadata({ - params, -}: generateMetadataProps): Promise { - // get all dirs in the project name and find the one that ends with the project name - const allDirs = fs.readdirSync( - path.join(process.cwd(), "public", "_strategies", params.projectName) - ); +export async function generateMetadata({ params }: generateMetadataProps): Promise { + // get all dirs in the project name and find the one that ends with the project name + const allDirs = fs.readdirSync( + path.join(process.cwd(), 'public', '_strategies', params.projectName) + ); - const strategyDir = allDirs.find((dir) => dir.endsWith(params.strategyName)); + const strategyDir = allDirs.find((dir) => dir.endsWith(params.strategyName)); - if (!strategyDir) { - throw new Error( - `No directory found for strategy: ${params.strategyName} in project: ${params.projectName}` - ); - } - return { - other: { - ...(await fetchMetadata( - new URL( - `/frames/${params.projectName}/${params.strategyName}/${params.deployment}`, - process.env.VERCEL_URL - ? `https://${process.env.VERCEL_URL}` - : "http://localhost:3000" - ) - )), - }, - }; + if (!strategyDir) { + throw new Error( + `No directory found for strategy: ${params.strategyName} in project: ${params.projectName}` + ); + } + return { + other: { + ...(await fetchMetadata( + new URL( + `/frames/${params.projectName}/${params.strategyName}/${params.deployment}`, + process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000' + ) + )) + } + }; } interface homeProps { - params: { - projectName: string; - strategyName: string; - deployment: string; - }; + params: { + projectName: string; + strategyName: string; + deployment: string; + }; } export default async function Home({ params }: homeProps) { - // get all dirs in the project name and find the one that ends with the project name - const allDirs = fs.readdirSync( - path.join(process.cwd(), "public", "_strategies", params.projectName) - ); + // get all dirs in the project name and find the one that ends with the project name + const allDirs = fs.readdirSync( + path.join(process.cwd(), 'public', '_strategies', params.projectName) + ); - const strategyDir = allDirs.find((dir) => dir.endsWith(params.strategyName)); + const strategyDir = allDirs.find((dir) => dir.endsWith(params.strategyName)); - if (!strategyDir) { - throw new Error( - `No directory found for strategy: ${params.strategyName} in project: ${params.projectName}` - ); - } + if (!strategyDir) { + throw new Error( + `No directory found for strategy: ${params.strategyName} in project: ${params.projectName}` + ); + } - const filePath = path.join( - process.cwd(), - "public", - "_strategies", - params.projectName, - strategyDir, - `${params.strategyName}.rain` - ); - const dotrainText = fs.readFileSync(filePath, "utf8"); + const filePath = path.join( + process.cwd(), + 'public', + '_strategies', + params.projectName, + strategyDir, + `${params.strategyName}.rain` + ); + const dotrainText = fs.readFileSync(filePath, 'utf8'); - return ( - - ); + return ; } diff --git a/app/[projectName]/[strategyName]/page.tsx b/app/[projectName]/[strategyName]/page.tsx index a872d155..d00ceb26 100644 --- a/app/[projectName]/[strategyName]/page.tsx +++ b/app/[projectName]/[strategyName]/page.tsx @@ -1,50 +1,46 @@ -import { fetchMetadata } from "frames.js/next"; -import { Metadata } from "next"; -import WebappFrame from "../../_components/WebappFrame"; -import fs from "fs"; -import path from "path"; +import { fetchMetadata } from 'frames.js/next'; +import { Metadata } from 'next'; +import WebappFrame from '../../_components/WebappFrame'; +import fs from 'fs'; +import path from 'path'; interface generateMetadataProps { - params: { - projectName: string; - strategyName: string; - }; + params: { + projectName: string; + strategyName: string; + }; } -export async function generateMetadata({ - params, -}: generateMetadataProps): Promise { - return { - other: { - ...(await fetchMetadata( - new URL( - `/frames/${params.projectName}/${params.strategyName}`, - process.env.VERCEL_URL - ? `https://${process.env.VERCEL_URL}` - : "http://localhost:3000" - ) - )), - }, - }; +export async function generateMetadata({ params }: generateMetadataProps): Promise { + return { + other: { + ...(await fetchMetadata( + new URL( + `/frames/${params.projectName}/${params.strategyName}`, + process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000' + ) + )) + } + }; } interface homeProps { - params: { - projectName: string; - strategyName: string; - }; + params: { + projectName: string; + strategyName: string; + }; } export default async function Home({ params }: homeProps) { - const filePath = path.join( - process.cwd(), - "public", - "_strategies", - params.projectName, - params.strategyName, - `${params.strategyName}.rain` - ); - const dotrainText = fs.readFileSync(filePath, "utf8"); + const filePath = path.join( + process.cwd(), + 'public', + '_strategies', + params.projectName, + params.strategyName, + `${params.strategyName}.rain` + ); + const dotrainText = fs.readFileSync(filePath, 'utf8'); - return ; + return ; } diff --git a/app/_components/FrameImage.tsx b/app/_components/FrameImage.tsx index f2c8c2cb..d5193047 100644 --- a/app/_components/FrameImage.tsx +++ b/app/_components/FrameImage.tsx @@ -5,14 +5,16 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => { return (
+ tw={`flex flex-col items-center justify-center h-full w-full text-center`} + >
{currentState.deploymentOption ? (
+ tw="absolute top-12 text-[30px] border rounded-full bg-gray-100 px-6 py-3" + > {currentState.deploymentOption.name}
) : ( @@ -20,7 +22,8 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => { )}
+ className="font-light md:px-32 max-w-[1200px] w-full flex flex-col justify-center flex-grow" + > {currentState.currentStep === 'start' ? (
{currentState.strategyName}
@@ -60,19 +63,22 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => { {currentState.currentStep === 'review' && currentState.deploymentOption ? ( + tw="text-left" + > + tw="border-t border-gray-300" + > @@ -113,10 +122,12 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => { + tw="border-t border-gray-300" + >
+ tw="px-4 py-2 text-[50px] font-bold text-gray-800" + > Review choices
+ tw="px-4 py-4 font-regular text-gray-700 w-[300px]" + > Deployment @@ -89,10 +95,12 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => {
+ tw="p-4 font-semibold text-gray-700 w-[300px] leading-tight" + > {field.name} @@ -104,7 +112,8 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => {
+ tw="px-4 py-2 text-[30px] font-bold text-gray-800" + > Deposits
+ tw="px-4 py-4 font-semibold text-gray-700 w-[300px] leading-tight" + > {tokenInfo.symbol} @@ -139,7 +150,8 @@ export const FrameImage = ({ currentState }: { currentState: FrameState }) => { height="139" viewBox="0 0 860 139" fill="none" - xmlns="http://www.w3.org/2000/svg"> + xmlns="http://www.w3.org/2000/svg" + > = ({ currentState }) => { - const [showTooltip, setShowTooltip] = useState(false); + const [showTooltip, setShowTooltip] = useState(false); - const handleClick = () => { - setShowTooltip(true); - getUrlWithState(); + const handleClick = () => { + setShowTooltip(true); + getUrlWithState(); - setTimeout(() => { - setShowTooltip(false); - }, 5000); - }; + setTimeout(() => { + setShowTooltip(false); + }, 5000); + }; - const getUrlWithState = async () => { - const url = new URL(window.location.href); - const jsonString = JSON.stringify(currentState); - const compressed = await compress(jsonString); - url.searchParams.set("currentState", compressed); - navigator.clipboard.writeText(url.href); - }; + const getUrlWithState = async () => { + const url = new URL(window.location.href); + const jsonString = JSON.stringify(currentState); + const compressed = await compress(jsonString); + url.searchParams.set('currentState', compressed); + navigator.clipboard.writeText(url.href); + }; - return ( -
- -
- Shareable URL copied to clipboard -
-
- ); + return ( +
+ +
+ Shareable URL copied to clipboard +
+
+ ); }; export default ShareStateAsUrl; diff --git a/app/_components/StrategyAnalytics.tsx b/app/_components/StrategyAnalytics.tsx index 9b08db9a..a42cb594 100644 --- a/app/_components/StrategyAnalytics.tsx +++ b/app/_components/StrategyAnalytics.tsx @@ -67,7 +67,8 @@ const StrategyAnalytics = ({ transactionId }: props) => { )} diff --git a/app/_components/SubmissionModal.tsx b/app/_components/SubmissionModal.tsx index 82392893..13eaa005 100644 --- a/app/_components/SubmissionModal.tsx +++ b/app/_components/SubmissionModal.tsx @@ -147,7 +147,8 @@ export const SubmissionModal = ({ href={ref.url} target="_blank" rel="noreferrer" - style={{ color: 'blue', textDecoration: 'underline' }}> + style={{ color: 'blue', textDecoration: 'underline' }} + > {ref.name} @@ -294,7 +295,8 @@ export const SubmissionModal = ({ onClick={() => setOpen(true)} color="primary" size="sm" - className=" from-blue-600 to-violet-600 bg-gradient-to-br"> + className=" from-blue-600 to-violet-600 bg-gradient-to-br" + > {buttonText} ) : ( @@ -340,7 +342,8 @@ export const SubmissionModal = ({ onClick={() => { setShowDisclaimer(false); submitStrategy(); - }}> + }} + > I understand @@ -354,7 +357,8 @@ export const SubmissionModal = ({
+ }`} + > {tokenDeposits.map((deposit, i) => (
+ }`} + > {i + 1}
@@ -399,7 +404,8 @@ export const SubmissionModal = ({ : submissionState === SubmissionStatus.Done ? 'bg-emerald-600 w-10 h-10' : 'bg-gray-400 w-10 h-10' - }`}> + }`} + > {currentState.deposits.length + 1}
@@ -426,7 +432,8 @@ export const SubmissionModal = ({
diff --git a/app/_components/TradesTable.tsx b/app/_components/TradesTable.tsx index 141d2feb..27a58fc2 100644 --- a/app/_components/TradesTable.tsx +++ b/app/_components/TradesTable.tsx @@ -24,13 +24,15 @@ const TradesTable = ({ trades }: props) => { {trade.tradeEvent.transaction.timestamp} navigator.clipboard.writeText(trade.tradeEvent.sender)} - className="cursor-pointer"> + className="cursor-pointer" + > {trade.tradeEvent.sender.slice(0, 5)}... {trade.tradeEvent.sender.slice(-1 * 5)} navigator.clipboard.writeText(trade.tradeEvent.transaction.id)} - className="cursor-pointer"> + className="cursor-pointer" + > {trade.tradeEvent.transaction.id.slice(0, 5)}... {trade.tradeEvent.transaction.id.slice(-1 * 5)} diff --git a/app/_components/WebappFrame.tsx b/app/_components/WebappFrame.tsx index d5cd43f1..c96e37c7 100644 --- a/app/_components/WebappFrame.tsx +++ b/app/_components/WebappFrame.tsx @@ -213,7 +213,8 @@ const WebappFrame = ({ dotrainText, deploymentOption }: props) => { key={buttonData.buttonText} onClick={async () => { await handleButtonClick(buttonData); - }}> + }} + > {buttonData.buttonText} ); @@ -235,7 +236,8 @@ const WebappFrame = ({ dotrainText, deploymentOption }: props) => { diff --git a/app/_components/WithdrawalModal.tsx b/app/_components/WithdrawalModal.tsx index e310a649..6e46afdd 100644 --- a/app/_components/WithdrawalModal.tsx +++ b/app/_components/WithdrawalModal.tsx @@ -111,7 +111,8 @@ export const WithdrawalModal = ({ vault }: WithdrawalModalProps) => { await withdraw(rawAmount); setOpen(false); })} - className="space-y-8"> + className="space-y-8" + > { - return { - flare: - "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.2/gn", - base: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.7/gn", - }; + return { + flare: + 'https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.2/gn', + base: 'https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.7/gn' + }; }; diff --git a/app/_schemas/failsafeWithNumbers.ts b/app/_schemas/failsafeWithNumbers.ts index 2af31d56..9edb5b45 100644 --- a/app/_schemas/failsafeWithNumbers.ts +++ b/app/_schemas/failsafeWithNumbers.ts @@ -1,15 +1,15 @@ -import yaml from "js-yaml"; +import yaml from 'js-yaml'; -const numberType = new yaml.Type("!", { - kind: "scalar", - resolve: (data) => { - return !isNaN(data) && !/^0x[0-9a-fA-F]{1,64}$/.test(data); - }, - construct: (data) => Number(data), - instanceOf: Number, - represent: (data) => Number(data), +const numberType = new yaml.Type('!', { + kind: 'scalar', + resolve: (data) => { + return !isNaN(data) && !/^0x[0-9a-fA-F]{1,64}$/.test(data); + }, + construct: (data) => Number(data), + instanceOf: Number, + represent: (data) => Number(data) }); export const FailsafeSchemaWithNumbers = yaml.FAILSAFE_SCHEMA.extend({ - implicit: [numberType], + implicit: [numberType] }); diff --git a/app/_services/buildProjectHome.tsx b/app/_services/buildProjectHome.tsx index cc8c20d8..88f5c4b1 100644 --- a/app/_services/buildProjectHome.tsx +++ b/app/_services/buildProjectHome.tsx @@ -1,69 +1,60 @@ -import fs from "fs"; -import path from "path"; -import yaml from "js-yaml"; -import { YamlData } from "../_types/yamlData"; -import { FailsafeSchemaWithNumbers } from "../_schemas/failsafeWithNumbers"; +import fs from 'fs'; +import path from 'path'; +import yaml from 'js-yaml'; +import { YamlData } from '../_types/yamlData'; +import { FailsafeSchemaWithNumbers } from '../_schemas/failsafeWithNumbers'; interface ProjectHomeData { - yamlDatas: StrategyFile[]; - webappMDText: string; - frameMDText: string; + yamlDatas: StrategyFile[]; + webappMDText: string; + frameMDText: string; } export interface StrategyFile { - fileName: string; - yamlData: YamlData; - descriptionMD: string; + fileName: string; + yamlData: YamlData; + descriptionMD: string; } -export const retrieveProjectData = async ( - projectName: string -): Promise => { - const dirPath = path.join( - process.cwd(), - "public", - "_strategies", - projectName - ); - const subDirs = fs - .readdirSync(dirPath, { withFileTypes: true }) - .filter((dirent) => dirent.isDirectory()) - .map((dirent) => dirent.name); +export const retrieveProjectData = async (projectName: string): Promise => { + const dirPath = path.join(process.cwd(), 'public', '_strategies', projectName); + const subDirs = fs + .readdirSync(dirPath, { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name); - const yamlDatas = subDirs.map((subDir) => { - const subDirPath = path.join(dirPath, subDir); + const yamlDatas = subDirs.map((subDir) => { + const subDirPath = path.join(dirPath, subDir); - // Find the .rain file in the subdirectory - const rainFile = fs - .readdirSync(subDirPath) - .find((filename) => filename.endsWith(".rain")); + // Find the .rain file in the subdirectory + const rainFile = fs.readdirSync(subDirPath).find((filename) => filename.endsWith('.rain')); - if (!rainFile) { - throw new Error(`No .rain file found in directory: ${subDirPath}`); - } + if (!rainFile) { + throw new Error(`No .rain file found in directory: ${subDirPath}`); + } - const rainFilePath = path.join(subDirPath, rainFile); - const descriptionFilePath = path.join(subDirPath, "description.md"); + const rainFilePath = path.join(subDirPath, rainFile); + const descriptionFilePath = path.join(subDirPath, 'description.md'); - // Read and parse the .rain file - const rainFileContent = fs.readFileSync(rainFilePath, "utf8"); - const yamlData = yaml.load(rainFileContent.split("---")[0], { - schema: FailsafeSchemaWithNumbers, - }) as YamlData; + // Read and parse the .rain file + const rainFileContent = fs.readFileSync(rainFilePath, 'utf8'); + const yamlData = yaml.load(rainFileContent.split('---')[0], { + schema: FailsafeSchemaWithNumbers + }) as YamlData; - // Read the description.md file - const descriptionMD = fs.readFileSync(descriptionFilePath, "utf8"); + // Read the description.md file + const descriptionMD = fs.readFileSync(descriptionFilePath, 'utf8'); - return { - fileName: rainFile.replace(".rain", ""), - yamlData, - descriptionMD, - }; - }); + return { + fileName: rainFile.replace('.rain', ''), + yamlData, + descriptionMD + }; + }); - // Reading the webapp.md and frame.md - const webappMDText = fs.readFileSync(path.join(dirPath, "webapp.md"), "utf8"); - const frameMDText = fs.readFileSync(path.join(dirPath, "frame.md"), "utf8"); + // Reading the webapp.md and frame.md + const webappMDText = fs.readFileSync(path.join(dirPath, 'webapp.md'), 'utf8'); + const frameMDText = fs.readFileSync(path.join(dirPath, 'frame.md'), 'utf8'); - return { yamlDatas, webappMDText, frameMDText }; + return { yamlDatas, webappMDText, frameMDText }; }; diff --git a/app/_services/dates.ts b/app/_services/dates.ts index 6af7c14b..d809eb59 100644 --- a/app/_services/dates.ts +++ b/app/_services/dates.ts @@ -1,9 +1,9 @@ -import dayjs from "dayjs"; -import bigIntSupport from "dayjs/plugin/bigIntSupport"; -import localizedFormat from "dayjs/plugin/localizedFormat"; +import dayjs from 'dayjs'; +import bigIntSupport from 'dayjs/plugin/bigIntSupport'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; dayjs.extend(bigIntSupport); dayjs.extend(localizedFormat); export function formatTimestampSecondsAsLocal(timestampSeconds: bigint) { - return dayjs(timestampSeconds * BigInt("1000")).format("L LT"); + return dayjs(timestampSeconds * BigInt('1000')).format('L LT'); } diff --git a/app/_services/frameButtons.tsx b/app/_services/frameButtons.tsx index 3610d6f7..51f3e204 100644 --- a/app/_services/frameButtons.tsx +++ b/app/_services/frameButtons.tsx @@ -27,7 +27,8 @@ export const getFrameButtons = ( ); @@ -45,7 +46,8 @@ export const getFrameButtons = ( target={{ query: { [button.buttonTarget]: button.buttonValue } }} post_url={{ query: { currentState: encodeURI(JSON.stringify(updatedState)) } - }}> + }} + > {button.buttonText} ); @@ -54,7 +56,8 @@ export const getFrameButtons = ( ); diff --git a/app/_services/frameTransactions.ts b/app/_services/frameTransactions.ts index c3ee945c..6e0949ed 100644 --- a/app/_services/frameTransactions.ts +++ b/app/_services/frameTransactions.ts @@ -1,101 +1,89 @@ -import { transaction } from "frames.js/core"; -import { Abi, encodeFunctionData, erc20Abi, parseUnits, toHex } from "viem"; -import { YamlData } from "@/app/_types/yamlData"; -import { FrameState } from "@/app/_types/frame"; -import { readContract } from "viem/actions"; -import { orderBookJson } from "@/public/_abis/OrderBook"; -import { getSubmissionTransactionData } from "./transactionData"; -import { getOrderDetailsGivenDeployment } from "./parseDotrainFrontmatter"; -import { getPublicClient } from "./getPublicClient"; +import { transaction } from 'frames.js/core'; +import { Abi, encodeFunctionData, erc20Abi, parseUnits, toHex } from 'viem'; +import { YamlData } from '@/app/_types/yamlData'; +import { FrameState } from '@/app/_types/frame'; +import { readContract } from 'viem/actions'; +import { orderBookJson } from '@/public/_abis/OrderBook'; +import { getSubmissionTransactionData } from './transactionData'; +import { getOrderDetailsGivenDeployment } from './parseDotrainFrontmatter'; +import { getPublicClient } from './getPublicClient'; -export const getApprovalTransaction = async ( - currentState: FrameState, - yamlData: YamlData -) => { - if (!currentState.deploymentOption) { - throw new Error( - "Deployment option is required to get approval transaction" - ); - } - // Get network and orderbook data from the yaml file - const deployment = - yamlData.deployments[currentState.deploymentOption.deployment]; - const order = yamlData.orders[deployment.order]; - const network = yamlData.networks[order.network]; +export const getApprovalTransaction = async (currentState: FrameState, yamlData: YamlData) => { + if (!currentState.deploymentOption) { + throw new Error('Deployment option is required to get approval transaction'); + } + // Get network and orderbook data from the yaml file + const deployment = yamlData.deployments[currentState.deploymentOption.deployment]; + const order = yamlData.orders[deployment.order]; + const network = yamlData.networks[order.network]; - const orderBook = yamlData.orderbooks[order.orderbook]; - const orderBookAddress = toHex(BigInt(orderBook.address)); + const orderBook = yamlData.orderbooks[order.orderbook]; + const orderBookAddress = toHex(BigInt(orderBook.address)); - const outputToken = yamlData.tokens[order.outputs[0].token]; - const outputTokenAddress = toHex(BigInt(outputToken.address)); + const outputToken = yamlData.tokens[order.outputs[0].token]; + const outputTokenAddress = toHex(BigInt(outputToken.address)); - const client = getPublicClient(network); - const outputTokenDecimals = await readContract(client, { - abi: erc20Abi, - address: outputTokenAddress, - functionName: "decimals", - }); + const client = getPublicClient(network); + const outputTokenDecimals = await readContract(client, { + abi: erc20Abi, + address: outputTokenAddress, + functionName: 'decimals' + }); - const depositAmount = parseUnits( - String(currentState.deposits[0].amount), - outputTokenDecimals - ); + const depositAmount = parseUnits(String(currentState.deposits[0].amount), outputTokenDecimals); - const approvalCalldata = encodeFunctionData({ - abi: erc20Abi, - functionName: "approve", - args: [orderBookAddress, depositAmount], - }); + const approvalCalldata = encodeFunctionData({ + abi: erc20Abi, + functionName: 'approve', + args: [orderBookAddress, depositAmount] + }); - // Return transaction data that conforms to the correct type - return transaction({ - chainId: `eip155:${network["chain-id"]}`, - method: "eth_sendTransaction", - params: { - abi: erc20Abi, - to: outputTokenAddress, - data: approvalCalldata, - }, - }); + // Return transaction data that conforms to the correct type + return transaction({ + chainId: `eip155:${network['chain-id']}`, + method: 'eth_sendTransaction', + params: { + abi: erc20Abi, + to: outputTokenAddress, + data: approvalCalldata + } + }); }; export const getSubmissionTransaction = async ( - currentState: FrameState, - yamlData: YamlData, - dotrainText: string + currentState: FrameState, + yamlData: YamlData, + dotrainText: string ) => { - if (!currentState.deploymentOption) { - throw new Error( - "Deployment option is required to get submission transaction" - ); - } + if (!currentState.deploymentOption) { + throw new Error('Deployment option is required to get submission transaction'); + } - const { addOrderCalldata, depositCalldatas } = - await getSubmissionTransactionData( - currentState, - dotrainText, - currentState.deposits - ); + const { addOrderCalldata, depositCalldatas } = await getSubmissionTransactionData( + currentState, + dotrainText, + currentState.deposits + ); - const multicallCalldata = encodeFunctionData({ - functionName: "multicall", - abi: orderBookJson.abi, - args: [[addOrderCalldata, ...depositCalldatas]], - }); + const multicallCalldata = encodeFunctionData({ + functionName: 'multicall', + abi: orderBookJson.abi, + args: [[addOrderCalldata, ...depositCalldatas]] + }); - const { orderBookAddress, network } = getOrderDetailsGivenDeployment( - yamlData, - currentState.deploymentOption.deployment - ); + const { orderBookAddress, network } = getOrderDetailsGivenDeployment( + yamlData, + currentState.deploymentOption.deployment + ); - // Return transaction data that conforms to the correct type - return transaction({ - chainId: `eip155:${network["chain-id"]}`, - method: "eth_sendTransaction", - params: { - abi: orderBookJson.abi as Abi, - to: orderBookAddress, - data: multicallCalldata, - }, - }); + // Return transaction data that conforms to the correct type + return transaction({ + chainId: `eip155:${network['chain-id']}`, + method: 'eth_sendTransaction', + params: { + abi: orderBookJson.abi as Abi, + to: orderBookAddress, + data: multicallCalldata + } + }); }; diff --git a/app/_services/parseDotrainFrontmatter.tsx b/app/_services/parseDotrainFrontmatter.tsx index fe666aa2..088b28b0 100644 --- a/app/_services/parseDotrainFrontmatter.tsx +++ b/app/_services/parseDotrainFrontmatter.tsx @@ -1,34 +1,31 @@ -import { toHex } from "viem"; -import { YamlData } from "../_types/yamlData"; -import _ from "lodash"; +import { toHex } from 'viem'; +import { YamlData } from '../_types/yamlData'; +import _ from 'lodash'; -export const getOrderDetailsGivenDeployment = ( - yamlData: YamlData, - deploymentOption: string -) => { - const deployment = yamlData.deployments[deploymentOption]; - const order = yamlData.orders[deployment.order]; - const orderBook = yamlData.orderbooks[order.orderbook]; - const orderBookAddress = toHex(BigInt(orderBook.address)); - const network = yamlData.networks[order.network]; +export const getOrderDetailsGivenDeployment = (yamlData: YamlData, deploymentOption: string) => { + const deployment = yamlData.deployments[deploymentOption]; + const order = yamlData.orders[deployment.order]; + const orderBook = yamlData.orderbooks[order.orderbook]; + const orderBookAddress = toHex(BigInt(orderBook.address)); + const network = yamlData.networks[order.network]; - const tokens = yamlData.tokens; + const tokens = yamlData.tokens; - const fullScenarioPath = deployment.scenario - .split(".") - .map((scenario, index, array) => - index === array.length - 1 ? scenario : scenario + ".scenarios" - ) - .join("."); - const scenario = _.get(yamlData.scenarios, fullScenarioPath); + const fullScenarioPath = deployment.scenario + .split('.') + .map((scenario, index, array) => + index === array.length - 1 ? scenario : scenario + '.scenarios' + ) + .join('.'); + const scenario = _.get(yamlData.scenarios, fullScenarioPath); - return { - deployment, - order, - orderBook, - orderBookAddress, - network, - tokens, - scenario, - }; + return { + deployment, + order, + orderBook, + orderBookAddress, + network, + tokens, + scenario + }; }; diff --git a/app/_services/tokenApproval.ts b/app/_services/tokenApproval.ts index f211c2d6..65d2c5ac 100644 --- a/app/_services/tokenApproval.ts +++ b/app/_services/tokenApproval.ts @@ -1,42 +1,38 @@ -import { erc20Abi, parseUnits, toHex } from "viem"; -import { FrameState } from "../_types/frame"; -import { YamlData } from "../_types/yamlData"; -import { readContract } from "viem/actions"; -import { getPublicClient } from "./getPublicClient"; +import { erc20Abi, parseUnits, toHex } from 'viem'; +import { FrameState } from '../_types/frame'; +import { YamlData } from '../_types/yamlData'; +import { readContract } from 'viem/actions'; +import { getPublicClient } from './getPublicClient'; export const hasEnoughTokenApproval = async ( - currentState: FrameState, - yamlData: YamlData, - requesterCustodyAddress: `0x${string}` + currentState: FrameState, + yamlData: YamlData, + requesterCustodyAddress: `0x${string}` ) => { - const deployment = - yamlData.deployments[currentState.deploymentOption?.deployment || ""]; - const order = yamlData.orders[deployment.order]; + const deployment = yamlData.deployments[currentState.deploymentOption?.deployment || '']; + const order = yamlData.orders[deployment.order]; - const orderBook = yamlData.orderbooks[order.orderbook]; - const orderBookAddress = toHex(BigInt(orderBook.address)); + const orderBook = yamlData.orderbooks[order.orderbook]; + const orderBookAddress = toHex(BigInt(orderBook.address)); - const network = yamlData.networks[order.network]; + const network = yamlData.networks[order.network]; - const outputToken = yamlData.tokens[order.outputs[0].token]; - const outputTokenAddress = toHex(BigInt(outputToken.address)); - const client = getPublicClient(network); - const outputTokenDecimals = await readContract(client, { - abi: erc20Abi, - address: outputTokenAddress, - functionName: "decimals", - }); + const outputToken = yamlData.tokens[order.outputs[0].token]; + const outputTokenAddress = toHex(BigInt(outputToken.address)); + const client = getPublicClient(network); + const outputTokenDecimals = await readContract(client, { + abi: erc20Abi, + address: outputTokenAddress, + functionName: 'decimals' + }); - // Get token approval for output token, if required - const depositAmount = parseUnits( - String(currentState.deposits[0].amount), - outputTokenDecimals - ); - const existingAllowance = await readContract(client, { - abi: erc20Abi, - address: outputTokenAddress, - functionName: "allowance", - args: [requesterCustodyAddress, orderBookAddress], - }); - return existingAllowance >= depositAmount; + // Get token approval for output token, if required + const depositAmount = parseUnits(String(currentState.deposits[0].amount), outputTokenDecimals); + const existingAllowance = await readContract(client, { + abi: erc20Abi, + address: outputTokenAddress, + functionName: 'allowance', + args: [requesterCustodyAddress, orderBookAddress] + }); + return existingAllowance >= depositAmount; }; diff --git a/app/_services/transactionData.ts b/app/_services/transactionData.ts index 1eb23b0f..b1c212f9 100644 --- a/app/_services/transactionData.ts +++ b/app/_services/transactionData.ts @@ -1,64 +1,54 @@ -import { getAddOrderCalldata } from "@rainlanguage/orderbook/common"; -import { - decodeFunctionData, - encodeFunctionData, - getAddress, - parseUnits, - toHex, -} from "viem"; -import { FrameState } from "../_types/frame"; -import { orderBookJson } from "@/public/_abis/OrderBook"; -import { TokenDeposit } from "../_components/SubmissionModal"; +import { getAddOrderCalldata } from '@rainlanguage/orderbook/common'; +import { decodeFunctionData, encodeFunctionData, getAddress, parseUnits, toHex } from 'viem'; +import { FrameState } from '../_types/frame'; +import { orderBookJson } from '@/public/_abis/OrderBook'; +import { TokenDeposit } from '../_components/SubmissionModal'; interface DecodedAddOrderCallData { - args?: { - validOutputs?: { - vaultId: string; - token: string; - }[]; - }[]; + args?: { + validOutputs?: { + vaultId: string; + token: string; + }[]; + }[]; } export const getSubmissionTransactionData = async ( - currentState: FrameState, - dotrainText: string, - tokenDeposits: TokenDeposit[] + currentState: FrameState, + dotrainText: string, + tokenDeposits: TokenDeposit[] ) => { - const addOrderCalldata = await getAddOrderCalldata( - dotrainText, - currentState.deploymentOption?.deployment || "" - ); - - // Get the vault ids from the decoded calldata - const decodedAddOrderCalldata = decodeFunctionData({ - data: toHex(addOrderCalldata), - abi: orderBookJson.abi, - }) as DecodedAddOrderCallData; - - const depositCalldatas = tokenDeposits.map((tokenDeposit) => { - const depositAmount = parseUnits( - String(tokenDeposit.amount), - tokenDeposit.tokenInfo.decimals - ); - - const vaultId = decodedAddOrderCalldata.args?.[0]?.validOutputs?.find( - (io) => - getAddress(io.token) === getAddress(tokenDeposit.tokenInfo.address) - )?.vaultId; - - if (!vaultId) { - throw new Error("Vault id not found"); - } - - return encodeFunctionData({ - functionName: "deposit2", - abi: orderBookJson.abi, - args: [tokenDeposit.tokenInfo.address, toHex(vaultId), depositAmount, []], - }); - }); - - return { - addOrderCalldata: toHex(addOrderCalldata), - depositCalldatas, - }; + const addOrderCalldata = await getAddOrderCalldata( + dotrainText, + currentState.deploymentOption?.deployment || '' + ); + + // Get the vault ids from the decoded calldata + const decodedAddOrderCalldata = decodeFunctionData({ + data: toHex(addOrderCalldata), + abi: orderBookJson.abi + }) as DecodedAddOrderCallData; + + const depositCalldatas = tokenDeposits.map((tokenDeposit) => { + const depositAmount = parseUnits(String(tokenDeposit.amount), tokenDeposit.tokenInfo.decimals); + + const vaultId = decodedAddOrderCalldata.args?.[0]?.validOutputs?.find( + (io) => getAddress(io.token) === getAddress(tokenDeposit.tokenInfo.address) + )?.vaultId; + + if (!vaultId) { + throw new Error('Vault id not found'); + } + + return encodeFunctionData({ + functionName: 'deposit2', + abi: orderBookJson.abi, + args: [tokenDeposit.tokenInfo.address, toHex(vaultId), depositAmount, []] + }); + }); + + return { + addOrderCalldata: toHex(addOrderCalldata), + depositCalldatas + }; }; diff --git a/app/_types/yamlData.ts b/app/_types/yamlData.ts index a47d05ef..970593e6 100644 --- a/app/_types/yamlData.ts +++ b/app/_types/yamlData.ts @@ -1,100 +1,100 @@ export interface Field { - binding: string; - name: string; - description: string; - min?: number; - presets?: Preset[]; + binding: string; + name: string; + description: string; + min?: number; + presets?: Preset[]; } export interface Preset { - name: string; - value: number; + name: string; + value: number; } export interface Referral { - name: string; - url: string; + name: string; + url: string; } export interface Deposit { - token: string; - min?: number; - presets?: number[]; - referrals?: Referral[]; + token: string; + min?: number; + presets?: number[]; + referrals?: Referral[]; } export interface DeploymentOption { - deployment: string; - name: string; - description: string; - fields: Field[]; - deposit: Deposit; - deposits: Deposit[]; + deployment: string; + name: string; + description: string; + fields: Field[]; + deposit: Deposit; + deposits: Deposit[]; } export interface Gui { - name: string; - description: string; - deployments: DeploymentOption[]; + name: string; + description: string; + deployments: DeploymentOption[]; } interface Network { - rpc: string; - "chain-id": number; - "network-id": number; - currency: string; + rpc: string; + 'chain-id': number; + 'network-id': number; + currency: string; } interface Orderbook { - address: string; + address: string; } interface Deployer { - address: string; - network: string; + address: string; + network: string; } interface Token { - network: string; - address: string; - decimals: number; + network: string; + address: string; + decimals: number; } interface OrderInputOutput { - token: string; - "vault-id": string; + token: string; + 'vault-id': string; } interface Order { - orderbook: string; - inputs: OrderInputOutput[]; - outputs: OrderInputOutput[]; - network: string; + orderbook: string; + inputs: OrderInputOutput[]; + outputs: OrderInputOutput[]; + network: string; } interface ScenarioBinding { - [key: string]: number; + [key: string]: number; } interface Scenario { - deployer: string; - runs: number; - bindings: ScenarioBinding; + deployer: string; + runs: number; + bindings: ScenarioBinding; } interface Deployment { - scenario: string; - order: string; + scenario: string; + order: string; } export interface YamlData { - networks: { [key: string]: Network }; - subgraphs: { [key: string]: string }; - orderbooks: { [key: string]: Orderbook }; - deployers: { [key: string]: Deployer }; - tokens: { [key: string]: Token }; - orders: { [key: string]: Order }; - scenarios: { [key: string]: Scenario }; - deployments: { [key: string]: Deployment }; - gui: Gui; + networks: { [key: string]: Network }; + subgraphs: { [key: string]: string }; + orderbooks: { [key: string]: Orderbook }; + deployers: { [key: string]: Deployer }; + tokens: { [key: string]: Token }; + orders: { [key: string]: Order }; + scenarios: { [key: string]: Scenario }; + deployments: { [key: string]: Deployment }; + gui: Gui; } diff --git a/app/my-strategies/[transactionId]/page.tsx b/app/my-strategies/[transactionId]/page.tsx index 83546996..97f1f1cd 100644 --- a/app/my-strategies/[transactionId]/page.tsx +++ b/app/my-strategies/[transactionId]/page.tsx @@ -1,13 +1,13 @@ -import StrategyAnalytics from "@/app/_components/StrategyAnalytics"; +import StrategyAnalytics from '@/app/_components/StrategyAnalytics'; interface props { - params: { - transactionId: string; - }; + params: { + transactionId: string; + }; } const Home = ({ params: { transactionId } }: props) => { - return ; + return ; }; export default Home; diff --git a/app/my-strategies/page.tsx b/app/my-strategies/page.tsx index 12a0ee36..57e7fa9d 100644 --- a/app/my-strategies/page.tsx +++ b/app/my-strategies/page.tsx @@ -43,7 +43,8 @@ export default function MyStrategies() { router.push( `${window.location.origin}/my-strategies/${order.addEvents[0].transaction.id}` ); - }}> + }} + > {order.network} {order.active ? ( diff --git a/components/ui/button.tsx b/components/ui/button.tsx index f8a9cbd1..7ed0f80c 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -1,59 +1,56 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } + 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline' + }, + size: { + default: 'h-10 px-4 py-2', + sm: 'h-9 rounded-md px-3', + lg: 'h-11 rounded-md px-8', + icon: 'h-10 w-10' + } + }, + defaultVariants: { + variant: 'default', + size: 'default' + } + } ); export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean; + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; - return ( - - ); - } + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + } ); -Button.displayName = "Button"; +Button.displayName = 'Button'; export { Button, buttonVariants }; diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index 6452bdea..7e8dd63b 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -40,7 +40,8 @@ const DialogContent = React.forwardRef< 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-12 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg', className )} - {...props}> + {...props} + > {children} {/* diff --git a/components/ui/form.tsx b/components/ui/form.tsx index ce264aef..d83be0ec 100644 --- a/components/ui/form.tsx +++ b/components/ui/form.tsx @@ -1,178 +1,169 @@ -"use client" +'use client'; -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { Slot } from "@radix-ui/react-slot" +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { Slot } from '@radix-ui/react-slot'; import { - Controller, - ControllerProps, - FieldPath, - FieldValues, - FormProvider, - useFormContext, -} from "react-hook-form" + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext +} from 'react-hook-form'; -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" +import { cn } from '@/lib/utils'; +import { Label } from '@/components/ui/label'; -const Form = FormProvider +const Form = FormProvider; type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath > = { - name: TName -} + name: TName; +}; -const FormFieldContext = React.createContext( - {} as FormFieldContextValue -) +const FormFieldContext = React.createContext({} as FormFieldContextValue); const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath >({ - ...props + ...props }: ControllerProps) => { - return ( - - - - ) -} + return ( + + + + ); +}; const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState, formState } = useFormContext() + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); - const fieldState = getFieldState(fieldContext.name, formState) + const fieldState = getFieldState(fieldContext.name, formState); - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } + if (!fieldContext) { + throw new Error('useFormField should be used within '); + } - const { id } = itemContext + const { id } = itemContext; - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState + }; +}; type FormItemContextValue = { - id: string -} + id: string; +}; -const FormItemContext = React.createContext( - {} as FormItemContextValue -) +const FormItemContext = React.createContext({} as FormItemContextValue); -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId() +const FormItem = React.forwardRef>( + ({ className, ...props }, ref) => { + const id = React.useId(); - return ( - -
- - ) -}) -FormItem.displayName = "FormItem" + return ( + +
+ + ); + } +); +FormItem.displayName = 'FormItem'; const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField() - - return ( -