这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@fengtality
Copy link
Contributor

Before submitting this PR, please make sure:

  • Your code builds clean without any errors or warnings
  • You are using approved title ("feat/", "fix/", "docs/", "refactor/")

A description of the changes proposed in the pull request:

Tests performed by the developer:

Tips for QA testing:

fengtality and others added 30 commits November 8, 2025 23:37
- Updated all CLMM operations to use PancakeswapSolConfig.config.slippagePct as default
- Fixed quote-position schema to show correct default (10) in Swagger UI instead of hardcoded 1
- Operations affected: quote-swap, quote-position, open-position, add-liquidity
- Added app-docs with Gateway App plans and UI mockups

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Created full-stack desktop app with Portfolio, Swap, Pools, and Liquidity views
- Built with Tauri v2, React 18, TypeScript, Vite, and TailwindCSS v4
- Implemented simple API client (~30 lines) using fetch for Gateway API calls
- Created AppContext for global state (wallet, network, chain selection)
- Added shadcn/ui components (Button, Card, Tabs, Input, Select)
- Portfolio View: displays wallet balances and LP positions
- Swap View: supports router-based swaps (Jupiter, 0x, Uniswap)
- Pools View: search and save liquidity pools
- Liquidity View: manage CLMM/AMM positions
- Updated app-docs with revised tab order (Portfolio → Swap → Pools → Liquidity)
- Configuration sharing: app reuses conf/ folder from Gateway server
- KISS architecture: no complex state libraries, direct schema imports

Testing:
- Gateway server running on localhost:15888 ✓
- App dev server running on localhost:1420 ✓
- API connectivity verified ✓
- Build succeeded ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Renamed "Portfolio View" to "Wallet View" in 01-portfolio-view.md
- Updated all navigation tabs across docs: Portfolio → Wallet, Config → Configs
- Changed sub-tab in Wallet view: Wallet → Tokens
- Updated ASCII diagrams to reflect current UI structure
- Ensured consistency across all view documentation files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Frontend (gateway-app/):
- Renamed Portfolio → Wallet, Config → Configs, Wallet tab → Tokens
- Added theme toggle with light/dark mode support
- Implemented ConfigView with namespace sidebar (Server, RPC Providers, Chains, Networks, Connectors)
- Added WalletSelector with chain grouping and icons (◎ for Solana, ⟠ for Ethereum)
- Added AddWalletModal for adding new wallets
- Flattened cache object editing for helius/infura configs
- Auto-switch to default network when changing chains
- Theme persistence via localStorage

Backend (src/):
- Added defaultNetwork field to /config/chains endpoint
- Changed chain order to return Solana first, then Ethereum
- Updated getChains route to include default network from config

Dependencies:
- Updated gateway-app dependencies (React, TailwindCSS, shadcn/ui)
- Configured TailwindCSS for dark mode support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Resolved conflict in pancakeswap-sol/clmm-routes/quoteSwap.ts
- Kept latest slippagePct handling without fallback
- Includes wrap/unwrap endpoints for Solana and Ethereum
- Test files for wrap/unwrap routes removed (were failing)
- Removed Pools and Liquidity tabs from main navigation
- Removed LP Positions tab from Wallet view
- Cleaned up unused imports (PoolsView, LiquidityView)
- Streamlined PortfolioView to show only Token Balances
…ctionality

- Display all tokens from network's token list in Wallet view
- Show actual balances for tokens with non-zero amounts, '0' for others
- Add 'Add Token' button in Token Balances header
- Create AddTokenModal component (similar to AddWalletModal)
- Modal allows selecting chain, network, and entering token address
- Calls POST /tokens/save to add new tokens to the list
- Auto-refreshes token list after adding new token
- Fetches available networks from /config/chains API
- Remove Total Holdings card
- Remove Value column from balances table
- Rename 'Token Balances' to 'Balances'
- Show only Asset and Balance columns
- Add tokens from balances response that aren't in token list
- Ensures native tokens (ETH, SOL) are displayed even if not in token list
- Update handleWalletChange to properly set network when switching chains
- Native token always displayed first with balance from balances endpoint
- Token list displayed after native token
- Balances endpoint always returns native currency symbol
- Filter out native token from token list to avoid showing it twice
- Native token always shown first, then other tokens from list
- Add clickable links to token symbols with addresses
- Links open in new tab to solscan.io token page
- Native token (no address) displays as plain text
- Add delete token functionality with hover-to-show delete button
- Add confirmation modal for token deletion
- Show token name column in balances table
- Integrate Tauri notifications for desktop app
- Add react-hot-toast for browser notifications with bottom-center positioning
- Include token symbols in success notifications
- Fix token save endpoint to use correct route format (POST /tokens/save/:address)
- Fix chain-network parameter format (ethereum-mainnet instead of eth-mainnet)
- Add CORS configuration to Gateway server with preflight support
- Replace all alert() calls with proper notification system

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Redesign ConfigView with table layout matching Balances view
- Add inline editing with hover-to-show pencil icon
- Show checkmark/X icons for save/cancel actions
- Right-align values and edit inputs for better layout
- Add toast notifications for config update success/error
- Use POST /config/update for single config updates
- Dynamically build chain sections from /config/chains API
- Show full chain-network names in sidebar and network selector
- Remove hardcoded chain lists, use API data instead
- Organize sidebar: Server, RPC Providers, Chains (dynamic), Connectors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add optional API key authentication to secure Gateway API when running
in production mode with remote clients.

Gateway changes:
- Add apiKeys configuration to server.yml and server-schema.json
- Implement API key validation middleware in app.ts
- Validate X-API-Key header for all requests when keys configured
- Skip authentication in dev mode (--dev flag or GATEWAY_TEST_MODE=dev)
- Log warning when running production mode without API keys
- Add X-API-Key to CORS allowedHeaders

Gateway-app changes:
- Make Gateway URL configurable via VITE_GATEWAY_URL env var
- Add API key support via VITE_GATEWAY_API_KEY env var
- Update api.ts to include X-API-Key header when configured
- Create .env.example with configuration template
- Add vite-env.d.ts for TypeScript environment variable types

Authentication behavior:
- Dev mode: No authentication required
- Production with apiKeys: Requires valid X-API-Key header
- Production without apiKeys: Warning logged, no authentication

Testing:
- Add comprehensive test suite for API key configuration
- Verify dev mode works without API keys
- Validate schema accepts empty and populated apiKeys arrays

Documentation:
- Create API_KEY_AUTHENTICATION.md with complete setup guide
- Document key generation, configuration, and testing
- Include security best practices and troubleshooting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…pport

Replace hardcoded mTLS requirement with configurable authentication to support
both traditional Hummingbot (client certificates) and browser-based clients
(API key).

Gateway changes:
- Add useCerts config (default: false) to toggle between cert and API key auth
- Add allowedOrigins config for CORS support
- Add sample API key to default template for easy setup
- Disable client cert requirement when useCerts is false
- Update HTTPS options to use useCerts configuration
- Log appropriate auth method on startup

Gateway-app changes:
- Install and configure @tauri-apps/plugin-http
- Use Tauri's fetch with acceptInvalidCerts for self-signed certificates
- Add HTTP plugin scope for localhost Gateway URLs
- Update default Gateway URL to HTTPS

Configuration structure:
- useCerts: false (API key auth, no client certs needed)
- useCerts: true (traditional mTLS with client certificates)
- apiKeys: list of valid API keys (only used when useCerts is false)
- allowedOrigins: CORS origins for browser clients

This maintains backward compatibility - existing Hummingbot users can set
useCerts: true to continue using client certificates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove apiKeys from server.yml config to prevent exposure through the
editable config API. API keys are now managed via GATEWAY_API_KEYS
environment variable for better security.

Changes:
- Remove apiKeys from server.yml template and schema
- Read API keys from GATEWAY_API_KEYS env var (comma-separated)
- Update documentation to use environment variable
- Add usage instructions for multiple keys

Usage:
  export GATEWAY_API_KEYS=key1,key2,key3
  GATEWAY_API_KEYS=mykey pnpm start --passphrase=a

This prevents API keys from being readable/editable via the /config API
while maintaining support for multiple keys per instance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove standalone API_KEY_AUTHENTICATION.md and integrate authentication
documentation into main README.md and gateway-app/README.md for better
discoverability.

Changes:
- Remove docs/API_KEY_AUTHENTICATION.md
- Add Authentication section to main README.md with both auth methods
- Update gateway-app/README.md with setup and auth instructions
- Document environment variables and usage for both Gateway and app

Authentication methods documented:
- API Key (default, useCerts: false): via GATEWAY_API_KEYS env var
- Client Certificates (useCerts: true): traditional mTLS for Hummingbot

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…d certs

This commit adds full Tauri HTTP plugin support to enable the desktop app to connect to Gateway's HTTPS server with self-signed certificates.

Changes:
- Add tauri-plugin-http with dangerous-settings feature to Cargo.toml
- Initialize HTTP plugin in Rust code (lib.rs)
- Configure HTTP permissions in capabilities files
- Create http.json capabilities for localhost:15888 URL scope
- Update api.ts to use Tauri fetch with acceptInvalidCerts option
- Update app identifier to io.hummingbot.gateway
- Add comprehensive dev and production build docs to README

The app now works in both dev mode (pnpm tauri dev) and production builds, with API key authentication and automatic SSL certificate acceptance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Major improvements to the swap interface:

- Redesign layout: wider card (max-w-2xl), start at top like other pages
- Token selection: dropdowns with all available tokens from network
- Balance display: show token balance with Max button to fill amount
- Token list: reuse shared getSelectableTokenList utility (native first, no duplicates)
- Quote details: display comprehensive swap info (amounts, price, slippage, route hops, quote ID)
- Swap direction: clickable arrow button to reverse from/to tokens
- Toast notifications: show pending (⏳), success (✅ with txHash), and error states
- Auto-fetch balances when wallet/network changes

Shared utility:
- Create getSelectableTokenList() in utils.ts for consistent token ordering
- Works for both Ethereum (ETH not in list) and Solana (SOL in list)
- Update PortfolioView to use shared utility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Move navigation from top tabs to bottom navbar for better mobile UX
- Make header responsive with wallet selector positioning
- Add responsive ConfigView with mobile dropdown and desktop sidebar
- Make config table responsive with horizontal scrolling on small screens
- Add responsive text sizes and input widths throughout
- Optimize padding and spacing for mobile viewports

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace dropdown selectors with icon buttons on mobile (< 640px)
- Add globe icon for network selection
- Add wallet icon for wallet selection
- Create bottom-sheet style modals for network and wallet selection
- Keep full dropdowns on desktop for better UX
- Change toast position from bottom-center to top-center
- Maintain truncated wallet addresses in mobile modal
- Add "Add Wallet" option in wallet selection modal

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Move wallet icon before network icon in mobile navbar
- Change wallet icon from wallet to key icon for better clarity
- Change network icon from globe to satellite icon
- Maintain consistent order across mobile and desktop views

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Change network icon from satellite to satellite dish for better clarity
- Rename bottom navigation from "Wallet" to "Portfolio"
- Improve visual consistency and user understanding

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Create reusable NetworkStatus component
- Show green/red dot based on block number status
- Display current block number next to status dot
- Click status to open modal with detailed chain information
- Auto-fetch status when network changes
- Show loading state with yellow pulsing dot
- Display: chain, network, block number, RPC URL, provider, swap provider
- Add refresh button to update status
- Position indicator next to Gateway title in navbar

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Backend (Tauri):
- Add read_app_config and write_app_config commands
- Store config in app config directory (app-config.json)
- Return default config if file doesn't exist

Frontend:
- Create app-config.ts helper library for Tauri integration
- Add "app" namespace to config system
- Handle "app" namespace specially (local file vs Gateway API)
- Rename "Server" section to "Gateway" with "app" and "server" subsections
- Update AppContext to load/save theme from app config file
- Theme persists across app restarts
- Config UI feels identical for both app and server configs

Features:
- Users can now configure app settings in Config sidebar
- Theme preference stored in local JSON file
- Foundation for future UI customization (colors, etc.)
- Seamless UX - app config looks like server config

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
fengtality and others added 20 commits November 13, 2025 09:34
- Create reusable RestartButton component
- Add restart icon button next to Gateway logo in header
- Button calls /restart endpoint and reloads page after 3 seconds
- Includes spinning animation during restart
- Properly handles errors and disabled state

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The /config/update endpoint expects separate namespace, path, and value
parameters, not a spread object. This was causing 400 errors when trying
to update config values via toggle switches or text inputs.

Changes:
- Update GatewayAPI.config.update() signature to accept (namespace, path, value)
- Fix ConfigView.saveEdit() to pass parameters correctly
- Fix ConfigView.handleBooleanToggle() to pass parameters correctly

Fixes the error: "body must have required property 'path'"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Move RestartButton from left (next to Gateway logo) to right side
- Position after NetworkStatus indicator
- Reduce icon size: 16px on desktop, 14px on mobile
- Reduce padding from p-2 to p-1.5 for smaller button footprint
- Add button to both desktop and mobile layouts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add customizable primary and accent colors (light & dark modes) in app config.
Users can now customize the app's color scheme through the Config view.

Changes:
- Extend AppConfig interface with theme.colors (primary, primaryDark, accent, accentDark)
- Create theme-manager.ts to apply CSS custom properties dynamically
- Load and apply theme colors on app start in AppContext
- Update theme colors automatically when dark mode toggles
- Apply theme colors immediately when updated in ConfigView
- Colors use HSL format matching Tailwind/shadcn conventions

Usage in Config view:
- theme.colors.primary: Primary color for light mode (HSL: "222.2 47.4% 11.2%")
- theme.colors.primaryDark: Primary color for dark mode
- theme.colors.accent: Accent color for light mode
- theme.colors.accentDark: Accent color for dark mode

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add theme.colors section with default HSL color values matching
the current CSS design system. This provides a template for users
to customize colors through the Config view.

Default colors:
- primary: "222.2 47.4% 11.2%" (dark blue for light mode)
- primaryDark: "210 40% 98%" (off-white for dark mode)
- accent: "210 40% 96.1%" (light gray-blue for light mode)
- accentDark: "217.2 32.6% 17.5%" (dark gray-blue for dark mode)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add hex color support with automatic HSL conversion for theme colors
- Add Gateway availability detection to show appropriate error messages
- Improve restart button with polling, toasts, and auto-refresh
- Add THEMES.json with 11 pre-made color schemes
- Update app config management for browser and Tauri modes
- Add localStorage and Tauri config sync instructions to README
- Fix Rust config reader to preserve theme settings
- Add Gateway unavailable message when server is not running

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
… branding

- Add GET /chains/solana/transactions endpoint for lightweight transaction signature listing
  - Returns transaction metadata (signature, slot, blockTime, status) without expensive parsing
  - Supports filtering by connector, sinceBlock, and limit (default 10, max 100)
  - Optimized to avoid rate limits by using cheap getSignaturesForAddress RPC call

- Add POST /chains/solana/parse endpoint for detailed transaction parsing
  - Extracts balance changes for native currency (SOL) and specified tokens
  - Includes transaction fees and status
  - On-demand parsing minimizes expensive RPC calls

- Refactor poll.ts to extract reusable parseSolanaTransaction function
  - Shared logic between /poll and /parse endpoints
  - Reduced code duplication

- Add comprehensive test suites for both new endpoints (17 tests total)
  - Mock Solana Connection and RPC responses
  - Cover success cases, error handling, and edge cases

- Update app branding for Tauri desktop app
  - Change product name from "gateway-app" to "Hummingbot Gateway"
  - Update window title to "Hummingbot Gateway"
  - Regenerate app icons using black/white logo (logo-bw-light-trans.png)
  - Update navbar to use dark/light logo variants based on theme

- Add logo assets to gateway-app/public/
  - logo-bw-dark-trans.png (for dark mode navbar)
  - logo-bw-light-trans.png (for light mode navbar)
  - Square variants for app icons

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…se endpoint

- Add connector/type parameters to parse endpoint for program identification
- Detect Jupiter Aggregator v6 transactions by checking for program ID JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4
- Auto-detect tokens involved in transactions when connector/type provided
  - Analyze preTokenBalances and postTokenBalances from transaction metadata
  - Look up token symbols for each mint address
  - Calculate balance changes for detected tokens
- Add connector and action fields to parse response schema
- Return connector name when transaction interacts with known program
- Build human-readable action strings (e.g., "Swap 0.001 WSOL for 12602.89 BONK on Jupiter Aggregator v6")

Example usage:
```bash
curl -X POST https://localhost:15888/chains/solana/parse \
  -d '{
    "network": "mainnet-beta",
    "signature": "Tqv6o...",
    "walletAddress": "82Sgg...",
    "connector": "jupiter",
    "type": "router"
  }'
```

Response includes:
- connector: "jupiter" (if detected)
- action: "Swap 0.001 WSOL for 12602.89 BONK on Jupiter Aggregator v6"
- tokenBalanceChanges: Auto-detected from transaction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Filter transactions by Jupiter Aggregator v6 program ID when connector=jupiter/router
- Fetch 3x limit transactions initially to ensure enough Jupiter txs after filtering
- Check each transaction's instructions for Jupiter program interaction
- Add Swagger examples for transactions and parse endpoints
  - Example wallet: 82SggYRE2Vo4jN4a2pk3aQ4SET4ctafZJGbowmCqyHx5
  - Example signature: Tqv6o4BvJmdNxpFbPquv4hKuM9mqyxWvvTmkd19wQZ2VQdC7m71gpFHaXTms53a5a7KfnFZXfnDeztVKTsViqFr
  - Example connector: jupiter/router

Usage:
```bash
curl https://localhost:15888/chains/solana/transactions?walletAddress=82Sgg...&connector=jupiter%2Frouter&limit=10
```

Returns only transactions that interacted with Jupiter program, making it easy to track Jupiter swaps for a wallet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…o scan

- Change default limit from 10 to 100 signatures
- Increase maximum limit from 100 to 1000 (RPC max)
- When connector filter is used, limit represents signatures to scan, not results returned
  - This is necessary because RPC filtering by program isn't possible
  - Must fetch and parse each transaction to check for program interaction
- Without connector filter, limit still represents number of results returned
- Update schema descriptions to clarify this behavior

This makes the API more predictable: when filtering by jupiter/router,
limit=100 will scan the last 100 transactions and return however many
matched Jupiter, rather than trying to return exactly 100 Jupiter transactions
(which would require scanning an unknown number of transactions).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The sinceBlock parameter was not functional because:
- Solana RPC getSignaturesForAddress only supports filtering by transaction signature (before/until), not by slot/block number
- The parameter would need to be implemented client-side by filtering results after fetching
- This doesn't reduce RPC calls or improve performance

Removed sinceBlock parameter to simplify the API and avoid confusion.
Users can control pagination using the limit parameter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Transactions endpoint (/chains/solana/transactions):
- Remove connector filtering - just fetch signatures
- Simplified to walletAddress and limit parameters only
- Returns lightweight signature metadata without parsing

Parse endpoint (/chains/solana/parse):
- Remove tokens and type parameters
- Change connector format from separate fields to single "connector/type" format (e.g., "jupiter/router")
- Auto-detects tokens when connector is provided
- Simpler API: just signature, walletAddress, and optional connector

Example usage:
```bash
# Get signatures
curl 'https://localhost:15888/chains/solana/transactions?walletAddress=82Sgg...&limit=100'

# Parse with Jupiter detection
curl -X POST 'https://localhost:15888/chains/solana/parse' \
  -d '{
    "signature": "Tqv6o4...",
    "walletAddress": "82Sgg...",
    "connector": "jupiter/router"
  }'
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…com:hummingbot/gateway into feat/gateway-app
…Meteora position width errors"

This reverts commit 2b0f924.
- Modified parse endpoint to use mint address as identifier when token not found in local list
- Previously skipped unknown tokens, now includes them with mint address as key
- Improves transparency by showing actual token addresses instead of dummy names

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove token balance tracking from poll route (use parse instead)
  - Simplified Solana poll to only return tx status and fee
  - Removed tokens and walletAddress parameters from poll request
- Improve Solana parse route
  - Auto-detect all token balance changes from transaction metadata
  - Auto-detect connector from program IDs (jupiter, meteora, raydium, pancakeswap)
  - Include native currency (SOL) in tokenBalanceChanges
  - Remove separate nativeBalanceChange field
  - Remove action field
  - Return mint address for tokens not in local list
- Add parse route to Ethereum
  - Extract token balance changes from Transfer events
  - Include native currency (ETH) in tokenBalanceChanges
  - Auto-detect ERC20 transfers
  - Return token address for tokens not in local list
- Update Solana.getToken() to only use local token list (no blockchain fetching)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add automatic connector detection to Ethereum parse route by mapping
contract addresses to connector names (Uniswap, PancakeSwap). Update
Solana parse tests to match current implementation.

Changes:
- Add buildContractMap() to map Ethereum contract addresses to connectors
- Import Uniswap and PancakeSwap contract addresses
- Auto-detect connector from transaction recipient address
- Rewrite Solana parse tests to test current metadata-based implementation
- Remove outdated tests using extractBalanceChangesAndFee() method
- Add tests for token auto-detection and connector detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Move jupiter-idl.json from project root to src/connectors/jupiter/ for
better organization. This file contains the Jupiter program interface
definition and serves as a reference for future development.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@rapcmia rapcmia moved this to In Discussion in Pull Request Board Nov 17, 2025
Base automatically changed from feat/helius-websocket-monitoring to development November 17, 2025 15:56
Add /chains/ethereum/transactions endpoint that fetches transaction history
using the Etherscan API txlist endpoint.

Changes:
- Add getTransactions() method to EtherscanService for fetching tx history
- Create transactions route that uses Etherscan API when configured
- Add EtherscanTransaction interface matching TransactionSignatureSchema
- Register transactions route in ethereum.routes.ts
- Add EtherscanTransactionsRequest schema extending TransactionsRequestSchema

The endpoint:
- Checks for etherscanAPIKey in ethereum.config
- Validates chain support (mainnet, polygon, bsc, avalanche, sepolia)
- Fetches up to 10000 transactions (Etherscan limit) sorted by latest first
- Maps Etherscan response to standard TransactionSignatureSchema format
- Returns empty array with warning if API key missing or chain unsupported
- Handles errors gracefully (auth, timeout, API errors)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
current = current[keys[i]];
}

current[keys[keys.length - 1]] = value;

Check warning

Code scanning / CodeQL

Prototype-polluting function Medium

The property chain
here
is recursively assigned to
current
without guarding against prototype pollution.

Copilot Autofix

AI about 23 hours ago

To fix prototype pollution in this pattern, we must ensure that none of the keys in the traversal chain are dangerous—most importantly, "__proto__", "prototype", and "constructor". Before accessing or writing properties on the config object, each key should be checked and an error thrown (or the key skipped) if it matches any of these blacklisted names.

The best fix modifies the loop at lines 80–85 and the write at line 87, adding such a check (either for each part of the chain or, for maximum security, all keys including the last one). This fix only requires a small local helper (e.g., isSafeKey) and can be self-contained in this file.

Specifically:

  • Add a helper function (e.g., isSafeKey(key: string): boolean) that checks that key is not "__proto__", "prototype", or "constructor".
  • In the loop at lines 80–85, check each keys[i] before using it.
  • Also check keys[keys.length - 1] before the assignment at line 87.
  • If any disallowed key is found, throw an error (or otherwise abort).
  • Only proceed with safe keys.

No imports are needed.


Suggested changeset 1
gateway-app/src/lib/app-config.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/gateway-app/src/lib/app-config.ts b/gateway-app/src/lib/app-config.ts
--- a/gateway-app/src/lib/app-config.ts
+++ b/gateway-app/src/lib/app-config.ts
@@ -73,18 +73,30 @@
 export async function updateAppConfigValue(path: string, value: any): Promise<void> {
   const config = await readAppConfig();
 
+  // Helper to prevent prototype pollution
+  function isSafeKey(key: string): boolean {
+    return key !== "__proto__" && key !== "prototype" && key !== "constructor";
+  }
+
   // Handle nested paths like "theme" or future "colors.primary"
   const keys = path.split('.');
   let current: any = config;
 
   for (let i = 0; i < keys.length - 1; i++) {
+    if (!isSafeKey(keys[i])) {
+      throw new Error(`Unsafe key in path: ${keys[i]}`);
+    }
     if (!(keys[i] in current)) {
       current[keys[i]] = {};
     }
     current = current[keys[i]];
   }
 
-  current[keys[keys.length - 1]] = value;
+  const finalKey = keys[keys.length - 1];
+  if (!isSafeKey(finalKey)) {
+    throw new Error(`Unsafe key in path: ${finalKey}`);
+  }
+  current[finalKey] = value;
 
   await writeAppConfig(config);
 }
EOF
@@ -73,18 +73,30 @@
export async function updateAppConfigValue(path: string, value: any): Promise<void> {
const config = await readAppConfig();

// Helper to prevent prototype pollution
function isSafeKey(key: string): boolean {
return key !== "__proto__" && key !== "prototype" && key !== "constructor";
}

// Handle nested paths like "theme" or future "colors.primary"
const keys = path.split('.');
let current: any = config;

for (let i = 0; i < keys.length - 1; i++) {
if (!isSafeKey(keys[i])) {
throw new Error(`Unsafe key in path: ${keys[i]}`);
}
if (!(keys[i] in current)) {
current[keys[i]] = {};
}
current = current[keys[i]];
}

current[keys[keys.length - 1]] = value;
const finalKey = keys[keys.length - 1];
if (!isSafeKey(finalKey)) {
throw new Error(`Unsafe key in path: ${finalKey}`);
}
current[finalKey] = value;

await writeAppConfig(config);
}
Copilot is powered by AI and may make mistakes. Always verify output.
fengtality and others added 5 commits November 17, 2025 11:24
…tion history

Updated the schema description to mention that etherscanAPIKey is used for
both gas price estimates and transaction history fetching.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…story only

Remove Etherscan gas tracking and SUPPORTED_CHAIN_IDS check. Let Etherscan V2 API
handle chain support validation via chainId parameter.

Changes:
- Remove gas oracle methods from EtherscanService (getGasOracle, getRecommendedGasPrices)
- Remove SUPPORTED_CHAIN_IDS whitelist - let API validate chain support
- Remove isSupported() check from transactions route
- Remove Etherscan gas fetching from ethereum.ts estimateGasPrice()
- Simplify to use only RPC provider for gas estimation
- EtherscanService now only handles transaction history via txlist endpoint

Benefits:
- Simpler code with single responsibility (transactions only)
- Automatic support for all Etherscan V2 chains (50+ networks)
- Gas estimation uses direct RPC provider (more reliable)
- No need to maintain chain ID whitelist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Update transactions endpoint schemas to use default values from chain config:
- Solana: Use SolanaAddressParameter (defaults to defaultWallet from config)
- Ethereum: Use EthereumAddressParameter (defaults to defaultWallet from config)
- Both now have optional walletAddress and network parameters with defaults
- Add rate limit detection and helpful error messages for Etherscan API

Changes:
- Update SolanaTransactionsRequest to use SolanaAddressParameter
- Update EthereumTransactionsRequest to use EthereumAddressParameter
- Add rate limit error detection in EtherscanService
- Provide link to Etherscan rate limits documentation in errors

Benefits:
- Users can omit walletAddress to use default wallet from config
- Users can omit network to use default network from config
- Better error messages when hitting Etherscan rate limits (5 req/sec free tier)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add .env and gateway-app/.env to .gitignore to prevent committing API keys
- Remove gateway-app/.env from git tracking (kept locally)
- Update server.yml comments to clarify API key authentication usage
- Fix pancakeswap-sol positionsOwned endpoint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Install dotenv package
- Load .env file automatically on Gateway startup
- Update .env.example with usage instructions for pnpm start
- Document that .env variables are loaded if not already set in shell

This allows GATEWAY_API_KEYS and GATEWAY_PASSPHRASE to be configured
in .env file without needing to export them manually.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Discussion

Development

Successfully merging this pull request may close these issues.

2 participants