Skip to main content
Glama
test-credentials.jsβ€’8.88 kB
#!/usr/bin/env node /** * Test script to verify Derive API credentials work properly * Tests both public and private endpoints */ import dotenv from 'dotenv'; import axios from 'axios'; import { Wallet } from 'ethers'; // Load .env file dotenv.config(); const DERIVE_ENVIRONMENT = process.env.DERIVE_ENVIRONMENT || "mainnet"; const DERIVE_WALLET = process.env.DERIVE_WALLET || ""; const DERIVE_PRIVATE_KEY = process.env.DERIVE_PRIVATE_KEY || ""; const API_BASES = { mainnet: "https://api.lyra.finance", testnet: "https://api-demo.lyra.finance", }; const BASE_API_URL = API_BASES[DERIVE_ENVIRONMENT]; console.log("πŸ” Derive API Credential Verification\n"); console.log("━".repeat(50)); // Check .env file console.log("\nπŸ“‹ Configuration Check:"); console.log(` Environment: ${DERIVE_ENVIRONMENT}`); console.log(` API URL: ${BASE_API_URL}`); console.log(` Wallet: ${DERIVE_WALLET ? "βœ… Set" : "❌ Missing"}`); console.log(` Private Key: ${DERIVE_PRIVATE_KEY ? "βœ… Set" : "⚠️ Not set (optional)"}`); if (!DERIVE_WALLET) { console.error("\n❌ ERROR: DERIVE_WALLET not set in .env"); process.exit(1); } // Validate wallet format if (!DERIVE_WALLET.match(/^0x[a-fA-F0-9]{40}$/)) { console.error(`\n❌ ERROR: Invalid wallet address format: ${DERIVE_WALLET}`); console.error(" Expected format: 0x followed by 40 hex characters"); process.exit(1); } console.log("\nβœ… Configuration looks good!"); console.log("\n━".repeat(50)); // Test 1: Public endpoint (no auth needed) async function testPublicEndpoint() { console.log("\n🌐 Test 1: Public Endpoint (get_currencies)"); console.log(" Testing: public/get_all_currencies"); try { const response = await axios.post(BASE_API_URL + "/public/get_all_currencies", {}, { headers: { "Content-Type": "application/json" }, timeout: 10000, }); if (response.data.error) { console.error(` ❌ API Error: ${JSON.stringify(response.data.error)}`); return false; } const currencies = response.data.result || response.data || []; console.log(` βœ… Success! Found ${currencies.length} currencies`); if (currencies.length > 0) { const currencyNames = currencies.slice(0, 3).map(c => c.currency || c); console.log(` Sample: ${currencyNames.join(", ")}`); } return true; } catch (error) { console.error(` ❌ Connection Error: ${error.message}`); if (error.response?.status === 404) { console.error(" API endpoint not reachable. Check DERIVE_ENVIRONMENT setting."); } return false; } } // Test 2: Private endpoint (requires auth) async function testPrivateEndpoint() { console.log("\nπŸ” Test 2: Private Endpoint (get_account)"); console.log(` Testing: private/get_account for wallet ${DERIVE_WALLET.slice(0, 6)}...`); const timestamp = Date.now().toString(); let signature = ""; if (DERIVE_PRIVATE_KEY) { try { // Use Ethereum wallet signing (EIP-191 personal_sign) const wallet = new Wallet(DERIVE_PRIVATE_KEY); signature = await wallet.signMessage(timestamp); console.log(` Signing wallet address: ${wallet.address}`); } catch (error) { console.warn(` ⚠️ Could not create signature: ${error.message}`); } } const headers = { "Content-Type": "application/json", "X-LyraWallet": DERIVE_WALLET, "X-LyraTimestamp": timestamp, }; if (signature) { headers["X-LyraSignature"] = signature; } const requestBody = { wallet: DERIVE_WALLET, }; try { const response = await axios.post(BASE_API_URL + "/private/get_account", requestBody, { headers, timeout: 10000, }); if (response.data.error) { const errorMsg = response.data.error.message || JSON.stringify(response.data.error); console.error(` ❌ API Error: ${errorMsg}`); if (errorMsg.includes("auth") || errorMsg.includes("signature")) { console.log(" πŸ’‘ Tip: Authentication failed. Check your wallet address."); } return false; } const account = response.data.result || response.data; console.log(` βœ… Success! Account accessed`); console.log(` Subaccounts: ${account.subaccount_ids?.length || 0}`); if (account.subaccount_ids && account.subaccount_ids.length > 0) { console.log(` First subaccount ID: ${account.subaccount_ids[0]}`); } return true; } catch (error) { if (error.response?.status === 401 || error.response?.status === 403) { console.error(` ❌ Authentication Failed (${error.response.status})`); console.log(" πŸ’‘ Possible causes:"); console.log(" β€’ DERIVE_WALLET not registered on this environment"); console.log(" β€’ Session key not registered properly"); console.log(" β€’ Using wrong environment (mainnet vs testnet)"); return false; } else { console.error(` ❌ Connection Error: ${error.message}`); return false; } } } // Test 3: Check if wallet has subaccounts async function testSubaccounts() { console.log("\nπŸ“Š Test 3: List Subaccounts"); const timestamp = Date.now().toString(); let signature = ""; if (DERIVE_PRIVATE_KEY) { try { // Use Ethereum wallet signing (EIP-191 personal_sign) const wallet = new Wallet(DERIVE_PRIVATE_KEY); signature = await wallet.signMessage(timestamp); } catch (error) { // Silent fail } } const headers = { "Content-Type": "application/json", "X-LyraWallet": DERIVE_WALLET, "X-LyraTimestamp": timestamp, }; if (signature) { headers["X-LyraSignature"] = signature; } const requestBody = { wallet: DERIVE_WALLET, }; try { const response = await axios.post(BASE_API_URL + "/private/get_subaccounts", requestBody, { headers, timeout: 10000, }); if (response.data.error) { console.error(` ⚠️ Could not fetch subaccounts: ${response.data.error.message}`); return null; } const subaccounts = response.data.result || response.data || []; console.log(` βœ… Found ${subaccounts.length} subaccount(s)`); if (subaccounts.length > 0) { subaccounts.forEach((sub, idx) => { console.log(` ${idx + 1}. ID: ${sub.subaccount_id} (Label: "${sub.label || "default"}")`); }); } else { console.log(" πŸ’‘ No subaccounts yet. Create one in the Derive app to start trading."); } return subaccounts; } catch (error) { console.error(` ❌ Error: ${error.message}`); return null; } } // Main test sequence async function runTests() { const publicOk = await testPublicEndpoint(); if (!publicOk) { console.log("\n⚠️ Public endpoint failed. Cannot continue testing."); console.log(" Check your network connection and DERIVE_ENVIRONMENT setting."); process.exit(1); } const privateOk = await testPrivateEndpoint(); if (privateOk) { await testSubaccounts(); } // Summary console.log("\n" + "━".repeat(50)); console.log("\nπŸ“‹ Summary:"); if (publicOk && privateOk) { console.log(" βœ… Public API: Working"); console.log(" βœ… Private API: Working"); console.log(" βœ… Credentials: Valid\n"); console.log("πŸŽ‰ Everything is set up correctly!"); console.log("\nYou can now use the Derive MCP server for:"); console.log(" β€’ Reading market data (no auth needed)"); console.log(" β€’ Accessing your account and positions"); console.log(" β€’ Placing and managing orders"); console.log("\nπŸ“Œ Next steps:"); console.log(" 1. Test with Claude: ask it to show market data"); console.log(" 2. Connect to Claude Desktop/Claude Code CLI"); console.log(" 3. Use natural language to trade and analyze markets"); process.exit(0); } else if (publicOk) { console.log(" βœ… Public API: Working"); console.log(" ❌ Private API: Not working\n"); console.log("⚠️ You can read public market data, but cannot access your account."); console.log("\nπŸ’‘ To fix private API access:"); console.log(" 1. Verify DERIVE_WALLET is correct (same address you use to sign in)"); console.log(" 2. Check you're on the correct environment (DERIVE_ENVIRONMENT)"); console.log(" 3. Create/register session keys in the Derive platform"); console.log(" 4. Wait for transactions to confirm"); process.exit(1); } else { console.log(" ❌ API Unreachable\n"); console.log("Cannot connect to Derive API. Check:"); console.log(" β€’ Network connectivity"); console.log(" β€’ DERIVE_ENVIRONMENT is 'mainnet' or 'testnet'"); console.log(" β€’ API status: https://status.lyra.finance"); process.exit(1); } } runTests().catch((error) => { console.error("\n❌ Unexpected error:", error.message); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/solenyaresearch0000/derive-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server