Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
name: Continuous Integration
name: CI

on:
pull_request:
types:
- opened
- reopened
- synchronize

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
check:
checks:
name: Lint, build and test
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: jdx/mise-action@v2
- name: Install mise
run: |
curl https://mise.run | MISE_VERSION=v2026.5.6 sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
echo "$HOME/.local/share/mise/shims" >> "$GITHUB_PATH"
export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"
mise install

- run: pnpm install --frozen-lockfile
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps

- run: pnpm run lint
- name: Lint
run: pnpm lint

- run: pnpm run build
- name: Build
run: pnpm build

- run: pnpm run test
- name: Test
run: pnpm test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ dist-ssr
opensrc/

.turbo
*.tsbuildinfo
*.tsbuildinfo
.pnpm-store/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule ".external/effect-smol"]
path = .external/effect-smol
url = https://github.com/Effect-TS/effect-smol.git
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# AGENTS.md

Instructions for AI coding agents working with this codebase.

## Commands

After each code change, run these commands to confirm that nothing is broken

- To lint and typecheck, run: `pnpm turbo lint --filter=@yieldxyz/perps-{package}`,
- For code formatting, run: `pnpm turbo format --filter=@yieldxyz/perps-{package}`,
- If a file is added, removed, or changed in `routes` folder, to generate route tree run: `pnpm turbo generate-routes --filter=@yieldxyz/perps-{package}`

## General rules

- Don't mix components/UI and logic - separate those two in hooks and components files
- All state handling should be done with `@effect-atom/atom-react`
- Use `effect` as much as possible. Don't use async/await
- Math/finance calculations and functions are placed in `packages/common/src/lib/math.ts`
- For manipulating array and records use `effect/Array` and `effect/Record`
- Don't use hooks `useMemo` or `useCallback` as we're using react-compiler
- During refactoring, avoid re-exporting functionality. Update imports in file thats importing this functionality

## Source code references

- Check `.external/effect-smol` for all references related to effect. Do not look up web for docs. They are not available yet as this is beta version
4 changes: 4 additions & 0 deletions apps/dashboard-react-example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VITE_PERPS_BASE_URL=
VITE_PERPS_API_KEY=
VITE_REOWN_PROJECT_ID=
VITE_MORALIS_API_KEY=
12 changes: 12 additions & 0 deletions apps/dashboard-react-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Perps Dashboard React Example</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions apps/dashboard-react-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "@yieldxyz/perps-dashboard-react-example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3102",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@yieldxyz/perps-dashboard": "workspace:*",
"react": "catalog:",
"react-dom": "catalog:"
},
"devDependencies": {
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@vitejs/plugin-react": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
}
19 changes: 19 additions & 0 deletions apps/dashboard-react-example/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Dashboard, type PerpsConfig } from "@yieldxyz/perps-dashboard";
import "@yieldxyz/perps-dashboard/styles.css";
import { createRoot } from "react-dom/client";
import "./styles.css";

const config: PerpsConfig = {
perpsBaseUrl: import.meta.env.VITE_PERPS_BASE_URL,
perpsApiKey: import.meta.env.VITE_PERPS_API_KEY,
reownProjectId: import.meta.env.VITE_REOWN_PROJECT_ID || undefined,
moralisApiKey: import.meta.env.VITE_MORALIS_API_KEY,
};

const rootElement = document.getElementById("root");

if (!rootElement) {
throw new Error("Root element not found");
}

createRoot(rootElement).render(<Dashboard config={config} />);
14 changes: 14 additions & 0 deletions apps/dashboard-react-example/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
html {
background: #121314;
}

body {
margin: 0;
min-width: 320px;
background: #121314;
}

#root {
min-height: 100vh;
background: #121314;
}
7 changes: 7 additions & 0 deletions apps/dashboard-react-example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noEmit": true
},
"include": ["src", "vite.config.ts"]
}
6 changes: 6 additions & 0 deletions apps/dashboard-react-example/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [react()],
});
4 changes: 4 additions & 0 deletions apps/dashboard-vanilla-example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VITE_PERPS_BASE_URL=
VITE_PERPS_API_KEY=
VITE_REOWN_PROJECT_ID=
VITE_MORALIS_API_KEY=
12 changes: 12 additions & 0 deletions apps/dashboard-vanilla-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Perps Dashboard Vanilla Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
16 changes: 16 additions & 0 deletions apps/dashboard-vanilla-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@yieldxyz/perps-dashboard-vanilla-example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3103",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@yieldxyz/perps-dashboard": "workspace:*"
},
"devDependencies": {
"vite": "catalog:"
}
}
16 changes: 16 additions & 0 deletions apps/dashboard-vanilla-example/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { mountDashboard } from "@yieldxyz/perps-dashboard/vanilla";
import "@yieldxyz/perps-dashboard/styles.css";
import "./styles.css";

const config = {
perpsBaseUrl: import.meta.env.VITE_PERPS_BASE_URL,
perpsApiKey: import.meta.env.VITE_PERPS_API_KEY,
reownProjectId: import.meta.env.VITE_REOWN_PROJECT_ID || undefined,
moralisApiKey: import.meta.env.VITE_MORALIS_API_KEY,
};

const dashboard = mountDashboard("#app", { config });

if (import.meta.hot) {
import.meta.hot.dispose(() => dashboard.unmount());
}
14 changes: 14 additions & 0 deletions apps/dashboard-vanilla-example/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
html {
background: #121314;
}

body {
margin: 0;
min-width: 320px;
background: #121314;
}

#app {
min-height: 100vh;
background: #121314;
}
3 changes: 3 additions & 0 deletions apps/dashboard-vanilla-example/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineConfig } from "vite";

export default defineConfig({});
4 changes: 4 additions & 0 deletions apps/widget-react-example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VITE_PERPS_BASE_URL=
VITE_PERPS_API_KEY=
VITE_REOWN_PROJECT_ID=
VITE_MORALIS_API_KEY=
12 changes: 12 additions & 0 deletions apps/widget-react-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Perps Widget React Example</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions apps/widget-react-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "@yieldxyz/perps-widget-react-example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3100",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@yieldxyz/perps-widget": "workspace:*",
"react": "catalog:",
"react-dom": "catalog:"
},
"devDependencies": {
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@vitejs/plugin-react": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
}
20 changes: 20 additions & 0 deletions apps/widget-react-example/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { type PerpsConfig, Widget } from "@yieldxyz/perps-widget";
import "@yieldxyz/perps-widget/styles.css";
import { createRoot } from "react-dom/client";
import "./styles.css";

const config: PerpsConfig = {
perpsBaseUrl: "https://perps.yield.xyz",
perpsApiKey: "e2d627cf-2ae3-4775-9fbc-76819c7cae38",
reownProjectId: "29e1b718ad16983a0705cf24d5b5b747",
moralisApiKey:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjhlNTk0NDE0LTg3NGMtNDZlMC1iMWNlLWU5ZjYzMjY1YWExMiIsIm9yZ0lkIjoiNDI2Nzk1IiwidXNlcklkIjoiNDM4OTk2IiwidHlwZSI6IlBST0pFQ1QiLCJ0eXBlSWQiOiI2YzMwMDY3Yi1kNDEyLTQwYjYtYTQ4OS0zYjEwM2ExNThjOGMiLCJpYXQiOjE3Mzc0NTA4NzcsImV4cCI6NDg5MzIxMDg3N30.pd8sKdRHdtlqoZVS7wb8Jyy2GLhhr95X8yW64W_gSC0",
};
Comment on lines +6 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove hardcoded credentials from client code.

Line 8 and Line 11 embed live-looking secrets directly in the frontend bundle. That is a credential leak risk; move them to import.meta.env and rotate the exposed keys/tokens.

Suggested fix
 const config: PerpsConfig = {
   perpsBaseUrl: "https://perps.yield.xyz",
-  perpsApiKey: "e2d627cf-2ae3-4775-9fbc-76819c7cae38",
-  reownProjectId: "29e1b718ad16983a0705cf24d5b5b747",
-  moralisApiKey:
-    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjhlNTk0NDE0LTg3NGMtNDZlMC1iMWNlLWU5ZjYzMjY1YWExMiIsIm9yZ0lkIjoiNDI2Nzk1IiwidXNlcklkIjoiNDM4OTk2IiwidHlwZSI6IlBST0pFQ1QiLCJ0eXBlSWQiOiI2YzMwMDY3Yi1kNDEyLTQwYjYtYTQ4OS0zYjEwM2ExNThjOGMiLCJpYXQiOjE3Mzc0NTA4NzcsImV4cCI6NDg5MzIxMDg3N30.pd8sKdRHdtlqoZVS7wb8Jyy2GLhhr95X8yW64W_gSC0",
+  perpsApiKey: import.meta.env.VITE_PERPS_API_KEY,
+  reownProjectId: import.meta.env.VITE_REOWN_PROJECT_ID,
+  moralisApiKey: import.meta.env.VITE_MORALIS_API_KEY,
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const config: PerpsConfig = {
perpsBaseUrl: "https://perps.yield.xyz",
perpsApiKey: "e2d627cf-2ae3-4775-9fbc-76819c7cae38",
reownProjectId: "29e1b718ad16983a0705cf24d5b5b747",
moralisApiKey:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjhlNTk0NDE0LTg3NGMtNDZlMC1iMWNlLWU5ZjYzMjY1YWExMiIsIm9yZ0lkIjoiNDI2Nzk1IiwidXNlcklkIjoiNDM4OTk2IiwidHlwZSI6IlBST0pFQ1QiLCJ0eXBlSWQiOiI2YzMwMDY3Yi1kNDEyLTQwYjYtYTQ4OS0zYjEwM2ExNThjOGMiLCJpYXQiOjE3Mzc0NTA4NzcsImV4cCI6NDg5MzIxMDg3N30.pd8sKdRHdtlqoZVS7wb8Jyy2GLhhr95X8yW64W_gSC0",
};
const config: PerpsConfig = {
perpsBaseUrl: "https://perps.yield.xyz",
perpsApiKey: import.meta.env.VITE_PERPS_API_KEY,
reownProjectId: import.meta.env.VITE_REOWN_PROJECT_ID,
moralisApiKey: import.meta.env.VITE_MORALIS_API_KEY,
};
🧰 Tools
🪛 Betterleaks (1.2.0)

[high] 8-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 11-11: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/widget-react-example/src/main.tsx` around lines 6 - 12, The PerpsConfig
object in main.tsx currently contains hardcoded secrets (perpsApiKey,
moralisApiKey, reownProjectId); remove these literals and load them from
environment variables via import.meta.env (e.g.
import.meta.env.VITE_PERPS_API_KEY, VITE_MORALIS_API_KEY, VITE_REOWN_PROJECT_ID)
when constructing the config used by PerpsConfig, validate presence and throw or
warn if missing, and rotate the exposed keys/tokens after replacement.


const rootElement = document.getElementById("root");

if (!rootElement) {
throw new Error("Root element not found");
}

createRoot(rootElement).render(<Widget config={config} />);
24 changes: 24 additions & 0 deletions apps/widget-react-example/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
html {
background: #131517;
}

body {
margin: 0;
min-width: 320px;
background: #131517;
}

#root {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: flex-start;
padding: 30px 16px;
box-sizing: border-box;
}

@media (min-width: 768px) {
#root {
padding: 32px;
}
}
7 changes: 7 additions & 0 deletions apps/widget-react-example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noEmit": true
},
"include": ["src", "vite.config.ts"]
}
6 changes: 6 additions & 0 deletions apps/widget-react-example/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [react()],
});
4 changes: 4 additions & 0 deletions apps/widget-vanilla-example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
VITE_PERPS_BASE_URL=
VITE_PERPS_API_KEY=
VITE_REOWN_PROJECT_ID=
VITE_MORALIS_API_KEY=
12 changes: 12 additions & 0 deletions apps/widget-vanilla-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Perps Widget Vanilla Example</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
16 changes: 16 additions & 0 deletions apps/widget-vanilla-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@yieldxyz/perps-widget-vanilla-example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port 3101",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@yieldxyz/perps-widget": "workspace:*"
},
"devDependencies": {
"vite": "catalog:"
}
}
Loading
Loading