Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e0caa54
[Feat] Added Derive API websockets integration
a-singh09 Jul 10, 2025
db49e58
[Feat] Implemented live data fetching for options and futures using D…
a-singh09 Jul 12, 2025
fe867fb
[Refactor] Removed duplicate interfaces
a-singh09 Jul 12, 2025
e9e1db4
[Fix] Updated subscription ID format and adjusted data fetching logic…
a-singh09 Jul 12, 2025
74a7182
[Feat] Enhanced DeriveAPIService with caching for option instruments …
a-singh09 Jul 13, 2025
8402801
[Feat] Added statistics fetching functionality to DeriveAPIService an…
a-singh09 Jul 13, 2025
c2289c1
[Feat] Integrated statistics fetching and formatting into futures tra…
a-singh09 Jul 14, 2025
aba0c5f
[Feat] Added PriceBox component for displaying market prices in optio…
a-singh09 Jul 14, 2025
817bfa9
[Feat] Implemented batch subscription and unsubscription methods for …
a-singh09 Jul 16, 2025
ff7d5ce
[Feat] Update date handling in options trading page and enhance optio…
a-singh09 Jul 16, 2025
fd8dfd7
[Feat] Enhance price box insertion logic based on market price relati…
a-singh09 Jul 16, 2025
f859a7d
[Feat] Implement option price click handling and update sidebar with …
a-singh09 Jul 16, 2025
87fde82
[Feat] Implement option grouping by option type
a-singh09 Jul 16, 2025
5637eb2
[Feat] Update futures ticker subscription management and cleanup logic
a-singh09 Jul 16, 2025
2686a6d
[Feat] Implement persistent option data subscriptions and enhance cac…
a-singh09 Jul 17, 2025
cb343ae
[Feat] Added derive authentication with testing
a-singh09 Jul 19, 2025
3ce505e
[Feat] Extend Derive API service for order operations and refactored …
a-singh09 Jul 19, 2025
2a797fb
feat: Implement Order Signing and Validation Services
a-singh09 Jul 19, 2025
9db04e2
[Feat] Integrate order functionality into options UI
a-singh09 Jul 20, 2025
87ec35c
[Feat] Modified authentication service to handle EOA and subaccount a…
a-singh09 Jul 22, 2025
c0e1426
[Refactor] Order Error Handling and Validation Logic
a-singh09 Jul 23, 2025
cf2033c
[Feat] Implement real-time order status updates
a-singh09 Jul 23, 2025
6331cc4
[Feat] Integrate live ticker data and update order status display icons
a-singh09 Jul 24, 2025
c36292f
[Refactor] Removed hardcoded values in options page
a-singh09 Jul 25, 2025
049aaf5
[Feat] Implement OrderBook component in Futures page
a-singh09 Jul 25, 2025
52737b5
[Refactor] Removed hardcoded wallet
a-singh09 Jul 26, 2025
006cc9a
[Feat] Added orders functionality in futures page
a-singh09 Jul 26, 2025
9f8a571
[Fix] Fixed authentication logic
a-singh09 Jul 30, 2025
9b40d20
[WIP] Order execution logic
a-singh09 Aug 5, 2025
0f7d44b
Fixed Ui Issues
DivyanshGoel259 Aug 7, 2025
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
32 changes: 32 additions & 0 deletions app/components/auth-test-loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Authentication Test Loader Component
*
* Loads authentication test utilities in development mode for browser console testing.
*/

"use client";

import { useEffect } from "react";

export default function AuthTestLoader() {
useEffect(() => {
// Only load test utilities in development mode
if (process.env.NODE_ENV === "development") {
// Dynamically import the test utilities to avoid bundling in production
import("../lib/auth-test-utils")
.then(() => {
console.log("🧪 Authentication test utilities are ready!");
console.log("💡 Try these commands in the console:");
console.log(" testAuth.testWalletConnection()");
console.log(" testAuth.testAuthentication()");
console.log(" testAuth.getAuthStatus()");
})
.catch((error) => {
console.warn("Failed to load auth test utilities:", error);
});
}
}, []);

// This component doesn't render anything
return null;
}
2 changes: 2 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Web3Providers } from "./web3-providers";
import { NetworkProvider } from "./context/network-context";
import StoreProvider from "./store-provider";
import { DarkModeProvider } from "./ui/header/use-dark-mode";
import AuthTestLoader from "./components/auth-test-loader";

export default function RootLayout({
children,
Expand All @@ -20,6 +21,7 @@ export default function RootLayout({
<NetworkProvider>
<Web3Providers>
<DarkModeProvider>
<AuthTestLoader />
<Navbar />
{children}
</DarkModeProvider>
Expand Down
81 changes: 81 additions & 0 deletions app/lib/auth-error-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Authentication Error Handler for Derive Protocol
*/

export interface AuthError {
type: string;
message: string;
recoverable: boolean;
retryable: boolean;
field?: string;
}

export interface RecoveryAction {
type: string;
label: string;
action: () => Promise<void>;
}

export class AuthErrorHandler {
private retryAttempts: Map<string, number> = new Map();

parseError(error: unknown, contextKey: string): AuthError {
if (error instanceof Error) {
return {
type: "AUTHENTICATION_ERROR",
message: error.message,
recoverable: true,
retryable: true,
};
}

return {
type: "UNKNOWN_ERROR",
message: "Unknown authentication error",
recoverable: true,
retryable: true,
};
}

getRecoveryActions(
error: AuthError,
actions: {
onRetry: () => Promise<void>;
onReconnectWallet: () => Promise<void>;
onManualRefresh: () => Promise<void>;
},
): RecoveryAction[] {
return [
{
type: "retry",
label: "Retry Authentication",
action: actions.onRetry,
},
{
type: "reconnect",
label: "Reconnect Wallet",
action: actions.onReconnectWallet,
},
];
}

shouldAutoRetry(error: AuthError, contextKey: string): boolean {
const attempts = this.retryAttempts.get(contextKey) || 0;
return error.retryable && attempts < 3;
}

getRetryDelay(contextKey: string): number {
const attempts = this.retryAttempts.get(contextKey) || 0;
return Math.min(1000 * Math.pow(2, attempts), 10000);
}

resetRetryAttempts(contextKey: string): void {
this.retryAttempts.delete(contextKey);
}

getUserFriendlyMessage(error: AuthError): string {
return error.message;
}
}

export const authErrorHandler = new AuthErrorHandler();
264 changes: 264 additions & 0 deletions app/lib/auth-test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/**
* Authentication Test Utilities
*
* Utilities for testing authentication functionality in the browser console.
* This helps verify that wallet connection and authentication are working properly.
*/

import { ethers } from "ethers";
import {
authenticationService,
type WalletProvider,
} from "./authentication-service";

declare global {
interface Window {
ethereum?: any;
testAuth?: any;
}
}

/**
* Create a wallet provider from MetaMask or other injected wallet
*/
async function createWalletProvider(): Promise<WalletProvider | null> {
try {
// Check if MetaMask or other wallet is available
if (!window.ethereum) {
console.error(
"❌ No wallet detected. Please install MetaMask or another Web3 wallet.",
);
return null;
}

// Request account access
console.log("🔗 Requesting wallet connection...");
const accounts = await window.ethereum.request({
method: "eth_requestAccounts",
});

if (!accounts || accounts.length === 0) {
console.error("❌ No accounts found. Please connect your wallet.");
return null;
}

const address = accounts[0];
console.log("✅ Wallet connected:", address);

// Create ethers provider and signer
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();

// Verify the signer address matches
const signerAddress = await signer.getAddress();
console.log("✅ Signer address:", signerAddress);

return {
address: signerAddress,
signer,
isConnected: true,
};
} catch (error) {
console.error("❌ Failed to create wallet provider:", error);
return null;
}
}

/**
* Test authentication flow
*/
async function testAuthentication(): Promise<void> {
try {
console.log("🚀 Starting authentication test...");

// Create wallet provider
const walletProvider = await createWalletProvider();
if (!walletProvider) {
return;
}

// Get initial authentication state
console.log("📊 Initial auth state:", authenticationService.getState());

// Subscribe to state changes
const unsubscribe = authenticationService.onStateChange((state) => {
console.log("🔄 Auth state changed:", {
isAuthenticated: state.isAuthenticated,
isAuthenticating: state.isAuthenticating,
hasSession: !!state.session,
lastError: state.lastError?.message || null,
retryCount: state.retryCount,
});
});

// Attempt authentication
console.log("🔐 Attempting authentication...");
try {
const session = await authenticationService.authenticate(walletProvider);
console.log("✅ Authentication successful!");
console.log("📋 Session details:", {
wallet_address: session.wallet_address,
session_id: session.session_id,
expires_at: new Date(session.expires_at * 1000).toISOString(),
access_token: session.access_token.substring(0, 20) + "...",
});

// Test session validation
console.log("🔍 Testing session validation...");
const isValid =
await authenticationService.validateSession(walletProvider);
console.log("✅ Session validation result:", isValid);

// Test auth headers
console.log("📝 Auth headers:", authenticationService.getAuthHeaders());
} catch (error) {
console.error("❌ Authentication failed:", error);

// Show user-friendly error if available
const friendlyError = authenticationService.getUserFriendlyError();
if (friendlyError) {
console.log("💬 User-friendly error:", friendlyError);
}

// Show recovery actions
const recoveryActions = authenticationService.getRecoveryActions();
if (recoveryActions.length > 0) {
console.log("🔧 Available recovery actions:");
recoveryActions.forEach((action, index) => {
console.log(` ${index + 1}. ${action.label}: ${action.description}`);
});
}
}

// Clean up subscription after 30 seconds
setTimeout(() => {
unsubscribe();
console.log("🧹 Cleaned up auth state subscription");
}, 30000);
} catch (error) {
console.error("❌ Test failed:", error);
}
}

/**
* Test logout functionality
*/
async function testLogout(): Promise<void> {
try {
console.log("🚪 Testing logout...");
await authenticationService.logout();
console.log("✅ Logout successful");
console.log("📊 Final auth state:", authenticationService.getState());
} catch (error) {
console.error("❌ Logout failed:", error);
}
}

/**
* Test session refresh
*/
async function testSessionRefresh(): Promise<void> {
try {
console.log("🔄 Testing session refresh...");
const session = await authenticationService.refreshSession();
console.log("✅ Session refresh successful");
console.log("📋 New session details:", {
expires_at: new Date(session.expires_at * 1000).toISOString(),
access_token: session.access_token.substring(0, 20) + "...",
});
} catch (error) {
console.error("❌ Session refresh failed:", error);
}
}

/**
* Get current authentication status
*/
function getAuthStatus(): void {
const state = authenticationService.getState();
console.log("📊 Current Authentication Status:");
console.log(" 🔐 Authenticated:", state.isAuthenticated);
console.log(" ⏳ Authenticating:", state.isAuthenticating);
console.log(" 👤 Wallet:", state.session?.wallet_address || "None");
console.log(" 🆔 Session ID:", state.session?.session_id || "None");
console.log(
" ⏰ Expires:",
state.session
? new Date(state.session.expires_at * 1000).toISOString()
: "None",
);
console.log(" ❌ Last Error:", state.lastError?.message || "None");
console.log(" 🔄 Retry Count:", state.retryCount);

if (state.recoveryActions.length > 0) {
console.log(" 🔧 Recovery Actions:");
state.recoveryActions.forEach((action, index) => {
console.log(` ${index + 1}. ${action.label}: ${action.description}`);
});
}
}

/**
* Test wallet connection without authentication
*/
async function testWalletConnection(): Promise<void> {
try {
console.log("🔗 Testing wallet connection...");
const walletProvider = await createWalletProvider();

if (walletProvider) {
console.log("✅ Wallet connection test successful");
console.log("📋 Wallet details:", {
address: walletProvider.address,
isConnected: walletProvider.isConnected,
});

// Test signing a simple message
console.log("✍️ Testing message signing...");
const message = "Test message for Derive Protocol";
const signature = await walletProvider.signer.signMessage(message);
console.log("✅ Message signed successfully");
console.log("📝 Signature:", signature.substring(0, 20) + "...");
}
} catch (error) {
console.error("❌ Wallet connection test failed:", error);
}
}

// Export test utilities to window object for console access
if (typeof window !== "undefined") {
window.testAuth = {
// Main test functions
testAuthentication,
testLogout,
testSessionRefresh,
testWalletConnection,
getAuthStatus,

// Direct access to service
authService: authenticationService,

// Helper functions
createWalletProvider,
};

console.log("🧪 Authentication test utilities loaded!");
console.log("📖 Available commands:");
console.log(" • testAuth.testWalletConnection() - Test wallet connection");
console.log(
" • testAuth.testAuthentication() - Test full authentication flow",
);
console.log(" • testAuth.getAuthStatus() - Check current auth status");
console.log(" • testAuth.testLogout() - Test logout");
console.log(" • testAuth.testSessionRefresh() - Test session refresh");
console.log(" • testAuth.authService - Direct access to auth service");
}

export {
testAuthentication,
testLogout,
testSessionRefresh,
testWalletConnection,
getAuthStatus,
createWalletProvider,
};
Loading