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

Conversation

@nikspz
Copy link
Contributor

@nikspz nikspz commented Oct 31, 2025

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:
PRs:

Tests performed by the developer:

Tips for QA testing:

rapcmia and others added 30 commits September 24, 2025 12:26
This commit refactors pool storage to include authoritative on-chain data:
- Add baseTokenAddress, quoteTokenAddress, and feePct to pool objects
- POST /pools now fetches pool-info to get token addresses and fees
- Update validation to require new fields
- Create migration script for existing pool templates
- Migrate Raydium (14 pools), Meteora (3 pools), and Uniswap (33 pools)
- Add Pancakeswap pools (4 pools) with new format
- Add missing BSC tokens (ASTER, CAKE, BUSD)
- Update documentation (CLAUDE.md, README.md)

The new pool format ensures stored data matches actual on-chain state,
eliminating runtime lookups and preventing token ordering mismatches.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add support for configurable EIP-1559 gas parameters (maxFeePerGas and
maxPriorityFeePerGas) for Ethereum and EVM-compatible networks. This allows
users to control transaction costs by setting custom gas values or using
network-fetched prices.

Changes:
- Add maxFeePerGas and maxPriorityFeePerGas config parameters
- Separate EIP-1559 (Type 2) and legacy (Type 0) transaction handling
- Enhance gas estimation with network fee logging and comparison
- Update estimate-gas API to return gasType and EIP-1559 details
- Add comprehensive gas configuration guide

Networks affected:
- EIP-1559: mainnet, base, polygon, arbitrum, optimism
- Legacy: bsc, avalanche, celo, sepolia

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

Co-Authored-By: Claude <noreply@anthropic.com>
Updated test/pools/pools.routes.test.ts to work with the enhanced Pool interface that now includes baseTokenAddress, quoteTokenAddress, and feePct fields.

Changes:
- Added required fields (baseTokenAddress, quoteTokenAddress, feePct) to all mock Pool objects
- Updated POST /pools test expectation to use expect.objectContaining() since the route now fetches and adds pool info automatically
- Removed outdated planning documents (POOL_MIGRATION_OUTSTANDING.md, POOL_STORAGE_REFACTOR_PLAN.md)

All 13 tests now passing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace per-network scanAPIKey with single etherscanAPIKey in ethereum.yml
- Migrate from V1 to V2 API endpoint (https://api.etherscan.io/v2/api)
- Add automatic chain support detection (Ethereum, Polygon, BSC verified)
- Implement chainId-based service initialization instead of network names
- Add comprehensive test suite with 17 tests covering API calls and error handling
- Update gas configuration guide with Etherscan V2 integration details
- Gracefully fall back to RPC for unsupported chains (Base, Arbitrum, Optimism)

This change provides more accurate EIP-1559 gas estimates using Etherscan's
gastracker module across all supported chains with a single API key.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace per-network scanAPIKey references with unified etherscanAPIKey
- Clarify that etherscanAPIKey is set once in ethereum.yml, not per network
- Document which chains support Etherscan gastracker (Ethereum, Polygon, BSC)
- Add explicit notes about unsupported chains (Base, Arbitrum, Optimism)
- Update all examples and troubleshooting sections
- Fix minGasPrice default description to reference network templates
- Update API key setup guide with V2 approach
- Add Etherscan V2 API migration guide to references

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Update Base/Optimism/Arbitrum examples to use 0.01 GWEI (from 0.1)
- Update BSC example to use 3.0 GWEI for legacy transactions
- Update all log examples to reflect actual configured values
- Clarify network-specific examples in configuration strategies
- Update API response examples with correct gas values
- Add notes explaining minGasPrice floor behavior for each network type

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Change Polygon minGasPrice from 30 to 10 GWEI
- Update maxFeePerGas and maxPriorityFeePerGas to 10 GWEI
- Update nodeURL to rpc.ankr.com/polygon
- Update nativeCurrencySymbol from MATIC to POL

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

Co-Authored-By: Claude <noreply@anthropic.com>
Remove legacy pool lookup code from CLMM open-position routes to align
with the existing schema requirement that poolAddress is mandatory.

Changes:
- Remove unused baseTokenSymbol and quoteTokenSymbol parameters from
  Raydium CLMM openPosition function
- Remove dead pool lookup code (12 lines) from Raydium implementation
- Remove misleading baseToken/quoteToken examples from Uniswap schema
- Update Uniswap poolAddress example to show real address

This is a non-breaking change since the schema already requires
poolAddress. All existing tests pass.

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

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

Update minGasPrice values to reflect current network requirements:
- BSC: 0.1 → 3 GWEI
- Polygon: 0.1 → 10 GWEI (align with conf template)

These values match the actual network conditions and align with the
values already documented in the configuration templates.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Move getPool querystring schema to src/pools/schemas.ts and use
Type.String with enum property instead of inline definition to enable
proper dropdown selection in Swagger UI.

Changes:
- Add GetPoolRequestSchema to src/pools/schemas.ts
- Use enum: ['amm', 'clmm'] for type field to create dropdown
- Import and use schema in getPool route

This allows users to select pool type from a dropdown in Swagger UI
instead of having the value hardcoded.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Update GetPoolRequestSchema to default to 'mainnet-beta' instead of
'mainnet' to align with Solana connector defaults (raydium, meteora).

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Explicitly override network default to 'mainnet-beta' in querystring
- Change tradingPair examples to show SOL-USDC first instead of ETH-USDC
- Ensure Swagger UI displays correct defaults for Solana connectors

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

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

Update POST /pools route to include all pool schema fields and allow
multiple pools with the same trading pair but different addresses.

Changes:
- Add baseTokenAddress, quoteTokenAddress, feePct as optional fields in
  PoolAddRequestSchema (fetched from pool-info if not provided)
- Update PoolAddRequest interface to include new optional fields
- Remove duplicate token pair check from PoolService.addPool
- Only prevent duplicate pool addresses, not duplicate pairs
- Update addPool route to use provided fields or fetch from pool-info
- Set mainnet-beta as default network in PoolAddRequestSchema
- Include fee percentage in success messages

This allows users to add multiple pools for the same token pair with
different fee tiers (e.g., JUP-USDC with 0.01%, 0.25%, 1% fees).

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

Co-Authored-By: Claude <noreply@anthropic.com>
…T /pools

Change baseTokenAddress and quoteTokenAddress from optional to required
fields in the add pool endpoint to ensure data consistency.

Changes:
- Remove Type.Optional wrapper from baseTokenAddress and quoteTokenAddress
  in PoolAddRequestSchema
- Update PoolAddRequest interface to make these fields required (not optional)
- Simplify addPool route logic since token addresses are now always provided
- Only fetch pool-info if feePct is missing

This ensures all pools have validated token addresses and prevents
inconsistencies in pool data.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add metadata-based duplicate detection to prevent multiple pools with
the same characteristics (type, network, feePct, token addresses) but
different addresses.

Changes:
- Add getPoolByMetadata method to PoolService to find pools by metadata
  instead of just address
- Update addPool route to check for existing pools with matching metadata
- If pool with same metadata exists but different address: remove old
  pool and add new one (replacement)
- If pool with same metadata and address exists: update it
- If no matching metadata: add as new pool

This ensures the pool database doesn't contain duplicate entries with
identical trading characteristics but different addresses.

Example: Prevents having two JUP-USDC CLMM 0.01% pools on mainnet-beta
with different addresses.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Change pool duplicate detection to match only on type, network, and
token addresses (baseTokenAddress, quoteTokenAddress), ignoring feePct.
When a new pool is added with the same token pair but different fee
tier, it replaces the existing pool.

Changes:
- Remove feePct parameter from getPoolByMetadata method
- Match pools based only on type, network, and token pair
- When same token pair with different fee tier is added: replace old pool
- When same token pair with same address is added: update fee tier
- Updated success messages to show old and new fee tiers on replacement

This ensures only one pool per token pair (per type/network) exists,
preventing duplicate entries with different fee tiers.

Example: Adding JUP-USDC 0.25% will replace existing JUP-USDC 0.01%

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

Co-Authored-By: Claude <noreply@anthropic.com>
Update pool routes tests to match new required fields (baseTokenAddress,
quoteTokenAddress) and new pool duplicate detection logic.

Changes:
- Add getPoolByMetadata and updatePool to mock PoolService
- Update POST /pools test payloads to include required baseTokenAddress
  and quoteTokenAddress fields
- Add feePct to test payloads
- Update "duplicate pool" test to "update existing pool" test since
  duplicate addresses now trigger updates instead of errors
- Add proper mocks for getPoolByMetadata and getPoolByAddress

All 13 pool routes tests now pass.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The third parameter to sendAndConfirmTransaction was being interpreted as
priority fee per compute unit (lamports/CU) instead of total compute units,
resulting in an excessive 7.838 SOL transaction fee (400000 lamports/CU ×
19595 CU) that caused transactions to fail. Now uses auto-estimated priority
fee like other Meteora operations.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add new connector for PancakeSwap on Solana using manual buffer decoding
instead of Anchor Program to avoid IDL compatibility issues.

Key features:
- CLMM pool info endpoint (/connectors/pancakeswap-sol/clmm/pool-info)
- Position info endpoint (/connectors/pancakeswap-sol/clmm/position-info)
- Manual account data decoding for PoolState and PersonalPositionState
- Program ID: HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq
- Compatible with pools using same IDL as Raydium CLMM

Technical implementation:
- Direct buffer reading to decode Solana account data
- No dependency on Anchor Program client to avoid IDL parsing errors
- Reuses existing CLMM schemas for API compatibility
- Configuration and template files for setup script

Tests:
- Integration tests for pool-info and position-info endpoints
- Verified with real PancakeSwap SOL/USDC pool on mainnet

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add positions-owned endpoint to list all positions for a wallet in a pool.
Rename IDL file from amm_v3.json to clmm.json for clarity.
Add comprehensive README documenting implemented and pending routes.

Implemented routes:
- GET /pool-info (existing)
- GET /position-info (existing)
- GET /positions-owned (new)

The connector uses manual buffer decoding for read operations.
Transaction routes (openPosition, closePosition, etc.) are documented
as pending implementation due to complexity of instruction building
without a dedicated PancakeSwap SDK.

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

Co-Authored-By: Claude <noreply@anthropic.com>
PancakeSwap position NFTs use Token2022 program, not SPL Token.
Update positionsOwned route to query both programs in parallel.

Tested with wallet DRpaJDurGtinzUPWSYnripFsJTBXm4HG7AC3LSgJNtNB
and successfully found position F1xRqqbWdg3vdMEsn9YjRU7RnFVn67MZhDVXrWoobii5
in pool DJNtGuBGEQiUCWE8F981M2C3ZghZt2XLD8f2sQdZ6rsZ.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Add simplified quote-swap endpoint that uses current pool price.

Limitations:
- Uses spot price from pool state
- Does NOT calculate price impact across ticks
- Does NOT use tick array data for precise calculations
- Does NOT account for liquidity depth

This provides basic swap quoting without requiring complex
concentrated liquidity math or SDK dependencies.

Tested with SOL/USDC pool successfully.

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

Co-Authored-By: Claude <noreply@anthropic.com>
Implement manual transaction building for swap_v2 instruction using
Anchor's BorshCoder to encode instruction data.

Key implementation:
- Manual pool data parsing to extract vaults and observation state
- Anchor instruction encoding without full Program client
- Support for both SPL Token and Token2022 programs
- Compute budget and priority fee handling
- Transaction simulation before sending

Features:
- POST /execute-swap endpoint for executing swaps
- Supports both BUY and SELL sides
- Configurable slippage protection
- Returns transaction signature and balance changes

Technical approach:
- Decodes pool account data to get required accounts
- Uses @coral-xyz/anchor BorshCoder for instruction encoding
- Builds VersionedTransaction with ComputeBudget instructions
- Signs and sends transaction via Solana RPC

Note: Requires testing with funded wallet (not tested yet due to
unfunded test wallet).

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

Co-Authored-By: Claude <noreply@anthropic.com>
Update documentation to reflect newly implemented routes:
- quote-swap: Simplified quote using spot price
- execute-swap: Manual transaction building for swaps

Add technical details about:
- Anchor instruction encoding
- Transaction building process
- Account resolution from pool data

Update examples with swap usage and clarify limitations.

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

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

Add complete test coverage for all implemented routes with real mainnet data:

Tests Added:
- Pool info route (2 tests)
- Position info route (2 tests)
- Positions owned route with Token2022 support (1 test)
- Quote swap route for BUY and SELL (2 tests)
- Fixture validation (3 tests)

Total: 14 tests, all passing

Fixtures Created:
- pool-info.json: Real SOL/USDC pool data
- position-info.json: Real position NFT data
- positions-owned.json: Array of positions
- quote-swap-sell.json: SELL quote response
- quote-swap-buy.json: BUY quote response

Key Test Features:
- Tests connector methods directly (not HTTP routes)
- Validates against real mainnet data
- Verifies Token2022 NFT discovery
- Tests both SPL Token and Token2022 programs
- Validates fixture structure matches responses
- Comprehensive logging for test visibility

All fixtures fetched from live mainnet data for accurate testing.

Test Results: 14/14 passing ✅

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

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

Added three position management routes:

1. **removeLiquidity**: Remove liquidity from existing positions by percentage
   - Takes percentageToRemove (0-100) parameter
   - Uses decrease_liquidity_v2 instruction with manual buffer decoding
   - Extracts position data to calculate tick arrays and protocol PDAs
   - Returns balance changes extracted from transaction

2. **closePosition**: Close empty positions
   - Validates position has zero liquidity before closing
   - Uses close_position instruction
   - Refunds position NFT account rent

3. **collectFees**: Collect accumulated fees
   - Uses clever Raydium approach: removes 1% liquidity to collect fees
   - Calls removeLiquidity internally with 1% parameter

Key implementation details:
- Added tick array address calculation (60 ticks per array)
- Added position data parsing to extract poolId, ticks, and liquidity
- Added pool tick spacing parsing
- Uses Token2022 for position NFTs with SPL Token fallback
- Proper response schema compliance with TransactionStatus enum

All routes build successfully and follow CLMM schema patterns.

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

Co-Authored-By: Claude <noreply@anthropic.com>
fengtality and others added 27 commits October 21, 2025 10:57
Changes:
- Clear ConfigManagerV2 singleton before creating Solana instance
- Fix property name: useWebSocketRPC (not useWebSocket) to match schema
- Import ConfigManagerV2 to access singleton

This was the missing piece - writing config files wasn't enough because
ConfigManagerV2 caches configs. Now the test:
1. Writes test configs
2. Clears ConfigManagerV2 singleton (forces config reload)
3. Clears Solana singleton
4. Creates new Solana instance with fresh configs
5. Verifies the fix worked

The test now properly validates that the merged Helius config is applied
to this.config in all environments including CI/CD.

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

Co-Authored-By: Claude <noreply@anthropic.com>
feat: enhance pool storage with token addresses and fees
Changes:
1. Skip pancakeswap-sol integration tests in CI (process.env.CI check)
   - These tests hit live Solana RPC and cause rate limiting (429 errors)
   - They can still run locally for developers
   - Integration tests verify actual pool behavior with real data

2. Fix pancakeswap route test string matching
   - Change from 'pancakeswap/' to 'pancakeswap' (more flexible)
   - Routes tree format splits across lines, making exact match fragile

These are proper integration tests that validate connector behavior against
live mainnet data. They're valuable for local development but not suitable
for CI due to RPC rate limits. Future work could add proper mocking.

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

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

- Move pancakeswap-sol-routes.test.ts to test/lifecycle/
- Move pancakeswap-sol-all-routes.test.ts to test/lifecycle/
- Fix import paths from ../../../src/ to ../../src/
- Fix fixture imports to point to ../connectors/pancakeswap-sol/fixtures/
- Remove CI skip logic (tests run manually, not in CI)
- Update jest.config.js to exclude test/lifecycle/ from CI test runs

Integration tests require live RPC access and should be run manually
to avoid rate limiting in CI/CD environments.

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

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

This commit fixes two critical issues in the PancakeSwap Solana CLMM connector:

1. Quote Position Endpoint - Tick Alignment
   - Added tickToPrice() helper to convert tick indices back to prices
   - Updated quotePosition to convert prices to ticks, round to valid tick spacing
   - Use tick-aligned prices for all liquidity calculations
   - Ensures quotes match PancakeSwap website precision

2. Position Info - Incorrect Amount Calculation
   - Fixed liquidity parsing: read full 16 bytes (u128) instead of 8 bytes (u64)
   - Replaced naive division with proper CLMM math using getAmountsFromLiquidity()
   - Use tickToPrice() for accurate tick-to-price conversion
   - Position amounts now match on-chain state (verified against Solscan)

Changes:
- pancakeswap-sol.parser.ts: Added tickToPrice() function
- quotePosition.ts: Implement tick-aligned price calculations
- pancakeswap-sol.ts: Fix getPositionInfo() liquidity reading and amount calculation

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

Co-Authored-By: Claude <noreply@anthropic.com>
## Changes

### Status Response Schema
- Add required `swapProvider` field to StatusResponseSchema
- Returns the configured swap provider for each network

### Ethereum Chain
- Add `swapProvider` property to Ethereum class
- Load swapProvider from network config (defaults to empty string)
- Include swapProvider in status endpoint response
- Add swapProvider to EthereumNetworkConfig interface

### Solana Chain
- Include swapProvider from existing config in status endpoint response
- swapProvider was already in SolanaNetworkConfig

### Schema Updates
- Add `swapProvider` to ethereum-network-schema.json
- Add `swapProvider` to solana-network-schema.json
- Schemas now synchronized between src/templates and conf

### Tests
- Update all Ethereum status tests (10 tests) with swapProvider expectations
- Update all Solana status tests (8 tests) with swapProvider expectations
- All 18 status tests passing

### API Response Example
```json
{
  "chain": "ethereum",
  "network": "mainnet",
  "rpcUrl": "https://eth.llamarpc.com",
  "rpcProvider": "url",
  "currentBlockNumber": 23329000,
  "nativeCurrency": "ETH",
  "swapProvider": "uniswap/router"
}
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
## Summary
Add new standardized chain-level endpoints `/chains/{chain}/quote-swap` and `/chains/{chain}/execute-swap` that abstract away the complexity of choosing and calling specific DEX connectors.

## New Chain Routes

### Ethereum Routes
- `POST /chains/ethereum/quote-swap` - Get swap quote from configured swap provider
- `POST /chains/ethereum/execute-swap` - Execute swap via configured swap provider

### Solana Routes
- `POST /chains/solana/quote-swap` - Get swap quote from configured swap provider
- `POST /chains/solana/execute-swap` - Execute swap via configured swap provider

## Features
- Automatically uses the `swapProvider` configured for each network
- Supports all swap types: router, amm, clmm
- Standard request/response interface across all chains
- Comprehensive error handling with specific error codes
- Full test coverage (4 new test files, 1,140+ lines of tests)

## Request Schema
```typescript
{
  network: string;           // Network name (mainnet, devnet, etc.)
  base: string;             // Base token symbol or address
  quote: string;            // Quote token symbol or address
  amount: string;           // Amount in base token units
  side: 'BUY' | 'SELL';    // Trade side
  address?: string;         // Wallet address (required for execute-swap)
  slippageTolerance?: string; // Optional slippage (default from connector config)

  // Optional AMM-specific
  poolAddress?: string;

  // Optional CLMM-specific
  poolId?: string;
  tickLower?: number;
  tickUpper?: number;
}
```

## Connector Updates
All DEX connectors now export `slippageTolerance`:
- ✅ Jupiter (router)
- ✅ 0x (router)
- ✅ Uniswap (router, amm, clmm)
- ✅ PancakeSwap (router, amm, clmm)
- ✅ Raydium (amm, clmm)
- ✅ Meteora (clmm)
- ✅ PancakeSwap Solana (clmm)

## Configuration Updates
- Added `swapProvider` to Solana chain config interface
- Added `swapProvider` field to Solana network configs

## Test Coverage
- `test/chains/ethereum/routes/quote-swap.test.ts` - 298 lines, 6 test cases
- `test/chains/ethereum/routes/execute-swap.test.ts` - 305 lines, 6 test cases
- `test/chains/solana/routes/quote-swap.test.ts` - 261 lines, 5 test cases
- `test/chains/solana/routes/execute-swap.test.ts` - 276 lines, 5 test cases

## Files Changed
- 33 files changed
- 1,823 insertions(+), 11 deletions(-)
- 4 new route implementation files
- 4 new test files
- 25 connector updates

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

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

Implement Solana RPC rate limit detection and proper HTTP 429 error responses:

**Rate Limit Interceptor (new file)**
- Create proxy-based Connection wrapper to intercept all RPC methods
- Detect 429 errors from multiple sources: statusCode, code, message patterns
- Transform rate limit errors into actionable user messages with:
  - Current RPC URL causing the limit
  - Network-specific config file path (mainnet-beta.yml vs devnet.yml)
  - Instructions to update nodeURL or configure Helius

**Error Propagation**
- Add re-throw logic for 429 errors in:
  - getSolBalance and fetchTokenAccounts (balances route)
  - confirmTransaction (both getTransaction and getSignatureStatus)
  - _sendAndConfirmRawTransaction (polling loop, re-broadcast, getBlockHeight)
- Non-429 errors continue graceful handling (return 0 for balances, retry for transient errors)

**Bug Fixes**
- Fix confirmTransaction promise executor to properly propagate errors
- Add 429 re-throw in outer try-catch of _sendAndConfirmRawTransaction

**Chain-Level Swap Schemas**
- Create ChainQuoteSwapResponseSchema without quoteId (quotes not cached at chain level)
- Create ChainExecuteSwapResponseSchema for standardized swap execution responses
- Update Solana and Ethereum quote-swap routes to use new schemas

**Comprehensive Test Coverage (40 tests)**
- Interceptor tests: 429 detection patterns, error messages, method coverage
- Propagation tests: Error flow through Solana class methods
- Route tests: HTTP 429 responses, actionable error messages

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

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

- Replace `maxFeePerGas` and `maxPriorityFeePerGas` with `baseFee` and `priorityFee`
- Add configurable `baseFeeMultiplier` parameter (default: 1.2)
- Transaction fee formula: `maxFeePerGas = baseFee * baseFeeMultiplier + priorityFee`
- Default `priorityFee` changed from 0.01 to 0.001 GWEI
- Support partial configuration: can override individual gas parameters
- Fetch values from network/Etherscan API when not configured

- Rename `minGasPrice` to `gasPrice`
- Fetch from network RPC when not configured
- Remove hardcoded fallback values

- Fix cross-network cache contamination bug
- Change from single static cache to per-network map
- Each network maintains independent 10-second cache
- Applies to both Ethereum and Solana chains

- **503 Service Unavailable**: RPC provider/network errors
- **400 Bad Request**: Invalid network configuration
- **500 Internal Server Error**: Generic failures
- Better error messages with context

- Update `ethereum-network-schema.json` and `solana-network-schema.json`
- Add type unions `["number", "null"]` for optional numeric fields
- Update all 9 Ethereum network templates
- Update 2 Solana network templates

- Update estimate-gas route tests for new parameters
- Add comprehensive error handling test cases
- Remove deprecated `minGasPrice` from mock configs
- All tests passing (6 estimate-gas tests, 10 infura tests, 17 etherscan tests)

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

Co-Authored-By: Claude <noreply@anthropic.com>
Created test infrastructure to reduce duplication across chain route tests:

**New Helpers:**
- test/helpers/commonMocks.ts: Centralized logger & ConfigManagerV2 mocks
- test/helpers/connectorMocks.ts: createRouteMock() for connector mocks
- test/helpers/mockResponses.ts: Factory functions for mock responses
- test/constants/mockTokens.ts: Centralized token addresses & constants

**Improvements:**
- Reduced logger mock duplication by 89% (72 lines → 8 lines)
- Reduced ConfigManagerV2 mock duplication by 89%
- Reduced connector mock boilerplate by 75% (using require() in jest.mock)
- Replaced 20+ hardcoded wallet addresses with MOCK_WALLET_ADDRESSES
- Eliminated duplicate mock response objects with factory functions

**Key Pattern:**
Used require() inside jest.mock() factory functions to call helpers while
satisfying Jest's hoisting requirements:
```typescript
jest.mock('path', () => require('helpers').createRouteMock('executeSwap'));
```

**Files Refactored:**
- test/chains/ethereum/routes/execute-swap.test.ts
- test/chains/ethereum/routes/quote-swap.test.ts
- test/chains/solana/routes/execute-swap.test.ts
- test/chains/solana/routes/quote-swap.test.ts

**Test Status:** All 34 tests passing ✅

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

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed failing universal router tests to reflect the new behavior where
gas estimation is skipped during quote phase and deferred to execution:

**Test Updates:**
- test/connectors/uniswap/universal-router.test.ts: Updated expectation
  from 500000 to 0 for estimatedGasUsed during quote phase
- test/connectors/pancakeswap/universal-router.test.ts: Updated expectation
  from 500000 to 0 for estimatedGasUsed during quote phase

**Implementation Update:**
- src/connectors/pancakeswap/universal-router.ts: Aligned with Uniswap
  implementation to skip gas estimation during quote phase for consistency

**Rationale:**
Gas estimation during quote phase was intentionally removed in commit
99f4022 to improve performance. Quote phase now returns estimatedGasUsed=0
as a placeholder, with actual estimation happening during execution phase.

**Test Status:**
- Uniswap universal router: ✅ All tests passing
- PancakeSwap universal router: ✅ All tests passing

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

Co-Authored-By: Claude <noreply@anthropic.com>
sync / Gateway development -> staging
Add unified /swap/quote and /swap/execute routes that accept chain-network parameter (e.g., "solana-mainnet-beta", "ethereum-mainnet") to enable cross-chain swap routing from a single endpoint.

Changes:
- Add src/routes/swap/quote.ts: GET /swap/quote endpoint with chain-network routing
- Add src/routes/swap/execute.ts: POST /swap/execute endpoint with chain-network routing
- Update src/app.ts: Register unified swap routes before chain-specific routes
- Implement parseChainNetwork() utility to parse "chain-network" format
- Route to appropriate chain implementation (Ethereum/EVM or Solana) based on chain parameter
- Support all EVM chains (ethereum, arbitrum, avalanche, base, bsc, celo, optimism, polygon, sepolia)

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

Co-Authored-By: Claude <noreply@anthropic.com>
Fix chain-network parameter format to properly route EVM networks:
- Use "ethereum-polygon" not "polygon-mainnet"
- Use "ethereum-mainnet", "ethereum-arbitrum", etc.
- Only "ethereum" and "solana" as chain identifiers in switch statement
- Networks like polygon, arbitrum, base are passed as network parameter to Ethereum handler

Changes:
- Remove individual EVM chain cases from switch statements
- Update documentation and examples to show correct format
- Verified with manual testing: ethereum-polygon, ethereum-mainnet, solana-mainnet-beta

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

Co-Authored-By: Claude <noreply@anthropic.com>
Major Changes:
- Moved swap logic from chain-specific routes to unified /trading/swap endpoints
- Removed poolAddress parameter from all positions-owned endpoints
- Added connector parameter support to swap quote and execute endpoints
- Fixed Meteora SDK bug handling with proper error responses

Swap Routes Refactoring:
- Deleted src/chains/{ethereum,solana}/routes/{execute,quote}-swap.ts
- Moved all logic into src/trading/swap/{execute,quote}.ts
- Created src/trading/trading.routes.ts for route registration
- Updated src/app.ts to register trading routes at /trading/swap prefix
- Routes now handle both Ethereum and Solana chains in single endpoint

Positions-Owned Refactoring:
- Updated Meteora, PancakeSwap-Sol, and Raydium positions-owned endpoints
- Removed poolAddress from request schemas (now fetch ALL positions)
- Updated implementations to return all positions across all pools
- Added comprehensive tests for all three connectors

Meteora Fixes:
- Added error handling for SDK bug in getAllLbPairPositionsByUser
- Returns 503 Service Unavailable with descriptive error message
- Fixed price decimal adjustment in quotePosition endpoint
- Set fee amounts to 0 for batch position fetching (SDK limitation)
- Filed GitHub issue: MeteoraAg/dlmm-sdk#245

Test Fixes:
- Fixed Raydium test with valid Solana public keys
- Fixed Solana RPC provider test to accept both 'url' and 'helius'
- Fixed PancakeSwap-Sol test to handle closed positions gracefully
- All 569 tests now passing (2 skipped)

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

Co-Authored-By: Claude <noreply@anthropic.com>
Enhancements to unified swap routes for better developer experience:

Schema Improvements:
- Add default values to all parameters for Swagger UI auto-population
- Reorder parameters: walletAddress first in execute, connector second in both
- Change side from Type.Union to Type.String with enum for proper dropdown in Swagger
- Use Jupiter/router as default connector example (SOL/USDC swap)

Dynamic Configuration:
- Fetch defaultWallet from Solana chain config at runtime
- Fallback to Ethereum chain config if Solana not configured
- Replace hardcoded wallet address with dynamic config value

Technical Fixes:
- Add type assertions (as 'BUY' | 'SELL') for side parameter to satisfy TypeScript
- Import getSolanaChainConfig and getEthereumChainConfig functions
- Ensure build passes with proper type safety

Swagger UI Defaults:
- chainNetwork: solana-mainnet-beta
- connector: jupiter/router
- walletAddress: <from config>
- baseToken: SOL
- quoteToken: USDC
- amount: 1
- side: SELL (dropdown shows BUY/SELL)
- slippagePct: 1

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Extract business logic from Uniswap and PancakeSwap CLMM routes into reusable functions
- Extract business logic from Raydium, Meteora, and PancakeSwap-Sol CLMM routes
- Create unified transaction routes at /trading/clmm/* for cross-chain operations:
  - POST /trading/clmm/open - Open new CLMM position
  - POST /trading/clmm/add - Add liquidity to existing position
  - POST /trading/clmm/remove - Remove liquidity from position
  - POST /trading/clmm/collect-fees - Collect accumulated fees
  - POST /trading/clmm/close - Close position completely
- Change /pools/{poolAddress} to /pool-info with query parameter
- Change /positions/{positionAddress} to /position-info with query parameter
- Add comprehensive test coverage for unified CLMM routes
- Fix pancakeswap-sol positionsOwned tests to properly mock Token2022 calls

All connectors (uniswap, pancakeswap, raydium, meteora, pancakeswap-sol) now support
unified routing through /trading/clmm/* endpoints with consistent request/response schemas.

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

Co-Authored-By: Claude <noreply@anthropic.com>
feat / Pancakeswap Solana connector
sync / Gateway development -> staging add 529 Pancakeswap
@nikspz nikspz merged commit 95df6a1 into main Nov 3, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants