Skip to content

Commit

Permalink
Merge pull request #72 from quiknode-labs/con-239-guideapp-idea-analy…
Browse files Browse the repository at this point in the history
…zing-wallet-trade-performance-and
  • Loading branch information
0xsergen authored Aug 15, 2024
2 parents 62ed005 + a7b1437 commit 7a61561
Show file tree
Hide file tree
Showing 27 changed files with 1,006 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_QUICKNODE_ENDPOINT = "YOUR_QUICKNODE_ETHEREUM_ENDPOINT_URL"
25 changes: 25 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local
.env

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
94 changes: 94 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# DEX Trade Performance Analyzer

## Introduction

This application is designed to analyze the trading performance of a crypto wallet, leveraging the capabilities of Syve's [DEX Price Data & Wallet Tracking APIs](https://marketplace.quicknode.com/add-on/syve-dex-price-data-and-wallet-tracking-api). The primary focus of this application is to provide users with detailed insights into wallet trading activities, including profit and loss metrics for each traded token.

For an in-depth guide on how to fetch data and develop further functionalities, refer to [our comprehensive guide on QuickNode](https://www.quicknode.com/guides/quicknode-products/marketplace/how-to-track-dex-wallet-trading-performance).

### Tech Stack

- Frontend Framework/Library: React
- Language: TypeScript
- Build Tool/Development Server: Vite
- Styling: Tailwind CSS

## Features

- **Overall Wallet Performance**: Displays total profit and loss, win rate, and other key metrics using Syve's Wallet Tracking API.
- **Token-Specific Performance**: Provides detailed trading metrics for each token held in the wallet.

## Getting Started

### Prerequisites

Before you begin, ensure you have the following:

- [Node.js](https://nodejs.org/en/) installed on your system.
- A QuickNode account with the [DEX Price Data & Wallet Tracking APIs](https://marketplace.quicknode.com/add-on/syve-dex-price-data-and-wallet-tracking-api) enabled.
- A code editor or an IDE (e.g., [VS Code](https://code.visualstudio.com/))
- [TypeScript](https://www.typescriptlang.org/) and [ts-node](https://typestrong.org/ts-node/)

> You can run the commands below to install TypeScript and ts-node globally to have TypeScript available across all projects.
```bash
npm install -g typescript ts-node
```

### Installation Dependencies

1. Clone the repository to your local machine:

```bash
git clone https://github.com/quiknode-labs/qn-guide-examples.git
```

2. Navigate to the project directory:

```bash
cd sample-dapps/ethereum-dex-trade-performance-analyzer
```

3. Install the necessary dependencies:

```bash
npm install
```

### Setting Environment Variables

Rename `.env.example` to `.env` and replace the `YOUR_QUICKNODE_ENDPOINT_URL` placeholder with your QuickNode Ethereum Node Endpoint. Make sure that the [DEX Price Data & Wallet Tracking APIs](https://marketplace.quicknode.com/add-on/syve-dex-price-data-and-wallet-tracking-api) are enabled.

```env
VITE_QUICKNODE_ENDPOINT="YOUR_QUICKNODE_ENDPOINT_URL"
```

> Please note that while we utilize `dotenv` for environment variable management, sensitive information like endpoints can still be visible on the frontend. This configuration is not recommended for production environments as-is.
### Running the Application

Run the development server:

```bash
npm run dev
```

Open [http://localhost:5173/](http://localhost:5173/) with your browser to see the application.

## Using the App

1. Input a wallet address.
2. Press **Analyze Wallet**.
3. View the overall and token-specific trading performance.

The **Wallet Performance Analyzer** will fetch the data using Syve's Wallet Tracking APIs, and display the results.

Overall Performance | Token Specific Performance
:-------------------------:|:-------------------------:
![App Overall Performance](public/app-overview.png) | ![App Token Specific Performance](public/app-token-details.png)

## Conclusion

Syve's [DEX Price Data & Wallet Tracking APIs](https://marketplace.quicknode.com/add-on/syve-dex-price-data-and-wallet-tracking-api) provide developers with powerful tools for analyzing wallet trading activities. By leveraging these APIs, developers can create applications that deliver valuable insights into crypto trading performance.

[QuickNode](https://quicknode.com/) offers many different marketplace add-ons, providing developers with the resources needed to create robust and feature-rich crypto applications. To learn more about how these APIs and other QuickNode add-ons can benefit your projects, please [contact us](https://www.quicknode.com/contact-us); we're eager to assist you!
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'

export default tseslint.config({
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
ignores: ['dist'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
})
13 changes: 13 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DEX Trade Performance Analyzer</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
35 changes: 35 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "dex-trade-analyzer",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@quicknode/sdk": "^2.3.0",
"dotenv": "^16.4.5",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.8.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20",
"axios": "^1.7.3",
"eslint": "^9.8.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"npm": "^10.8.2",
"postcss": "^8.4.41",
"tailwindcss": "^3.4.9",
"typescript": "^5.5.3",
"typescript-eslint": "^8.0.0",
"vite": "^5.4.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}
95 changes: 95 additions & 0 deletions sample-dapps/ethereum-dex-trade-performance-analyzer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useState } from "react";
import { OverallStats } from "./interfaces/OverallStats";
import { TokenPerformance } from "./interfaces/TokenPerformance";
import {
getWalletLatestTotalPerformance,
getWalletLatestPerformancePerToken,
} from "./services/api";
import WalletSearch from "./components/WalletSearch";
import OverallStatsDisplay from "./components/OverallStatsDisplay";
import TokenPerformanceTable from "./components/TokenPerformanceTable";

const App: React.FC = () => {
const [overallStats, setOverallStats] = useState<OverallStats | null>(null);
const [tokenPerformance, setTokenPerformance] = useState<TokenPerformance[]>(
[]
);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [dataFetched, setDataFetched] = useState<boolean>(false);

const handleSearch = async (address: string) => {
setLoading(true);
setError(null);
setDataFetched(false);

try {
const [overallStatsData, tokenPerformanceData] = await Promise.all([
getWalletLatestTotalPerformance(address),
getWalletLatestPerformancePerToken(address),
]);

setOverallStats(overallStatsData);
setTokenPerformance(tokenPerformanceData.data || []);
setDataFetched(true);
} catch (err) {
if (
err instanceof Error &&
err.message.includes("does not exist/is not available")
) {
setError(
"Add-on is not enabled. Please visit your QN dashboard and enable the add-on."
);
} else {
setError("Error fetching wallet data. Please try again.");
}
} finally {
setLoading(false);
}
};

return (
<div className="min-h-screen bg-gray-100 py-6 px-4 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
<div className="bg-white shadow-xl rounded-lg overflow-hidden">
<div className="px-4 py-5 sm:p-6">
<h1 className="text-3xl font-bold text-center text-primary-600 mb-8">
DEX Trade Performance Analyzer
</h1>
<WalletSearch onSearch={handleSearch} />
{loading && <p className="text-center mt-4">Loading...</p>}
{error && <p className="text-center mt-4 text-red-500">{error}</p>}
{dataFetched && overallStats && (
<div className="mt-8">
<h2 className="text-2xl font-semibold text-primary-600 mb-4">
Overall Performance
</h2>
<OverallStatsDisplay stats={overallStats} />
</div>
)}
{dataFetched && tokenPerformance.length > 0 && (
<div className="mt-8">
<h2 className="text-2xl font-semibold text-primary-600 mb-4">
Token Performance
</h2>
<TokenPerformanceTable performance={tokenPerformance} />
</div>
)}
{dataFetched && tokenPerformance.length === 0 && (
<p className="text-center mt-4 text-gray-500">
No token performance data available for this wallet.
</p>
)}
{!loading && !error && !dataFetched && (
<p className="text-center mt-4 text-gray-500">
Enter a wallet address to see the analysis.
</p>
)}
</div>
</div>
</div>
</div>
);
};

export default App;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7a61561

Please sign in to comment.