Feat multichain wallets - #645
Closed
VeXHarbinger wants to merge 16 commits into
Closed
Conversation
… all routes
All endpoints previously showed only 'mainnet'/'mainnet-beta' in Swagger examples,
leaving BSC (and other EVM networks: arbitrum, base, polygon, avalanche, optimism,
celo) invisible to users browsing /docs.
Updated files and what changed:
- src/schemas/chain-schema.ts: EstimateGasRequest, BalanceRequest, TokensRequest,
PollRequest, StatusRequest — add network description + examples incl. bsc,
arbitrum, base (used by /chains/ethereum/{tokens,balances,status,estimateGas,poll})
- src/schemas/amm-schema.ts: GetPoolInfoRequest (chainNetwork+network), AddLiquidity,
RemoveLiquidity, GetPositionInfoRequest, QuoteSwapRequest, ExecuteSwapRequest —
add network/chainNetwork descriptions + examples incl. ethereum-bsc, bsc
- src/schemas/clmm-schema.ts: FetchPoolsRequest, GetPositionsOwnedRequest,
GetPoolInfoRequest (chainNetwork+network), GetPositionInfoRequest, OpenPosition,
AddLiquidity, RemoveLiquidity, CollectFees, ClosePosition, QuoteSwap, ExecuteSwap —
add network/chainNetwork descriptions + examples incl. ethereum-bsc, bsc
- src/tokens/schemas.ts: TokenListQuerySchema, TokenViewQuerySchema,
TokenAddRequestSchema, TokenRemoveQuerySchema — chain description updated to clarify
'ethereum = all EVM networks incl. BSC'; network examples add bsc/arbitrum/base/polygon;
FindTokenQuerySchema chainNetwork examples add ethereum-bsc first
- src/pools/schemas.ts: PoolListRequestSchema, PoolAddRequestSchema,
GetPoolRequestSchema — network examples add bsc/arbitrum/base; connector
examples add pancakeswap; chain descriptions updated; FindPoolsQuerySchema
chainNetwork examples put ethereum-bsc first, connector examples updated
- src/pools/routes/removePool.ts: inline querystring network examples add bsc
- src/pools/routes/getPool.ts: tradingPair examples add WBNB-USDT, CAKE-USDT
Pre-existing test failures (chain-network-parsing: 2 tests) unchanged.
…to agent instructions
…warn on corrupt files, expanded test coverage - addWallet/createWallet: throw 400 'Either chain or chainNetwork is required' when neither field is provided (fixes silent Unrecognized chain name: undefined error) - getWallets: replace silent catch with logger.warn on corrupted/unreadable wallet files so operators are notified of misrouted wallets (addresses fengtality important item) - test/wallet/wallet-network-support.test.ts: add 7 new test cases covering (1) corrupted wallet file triggers warn + defaults to chain default network (2-3) missing chain and missing chainNetwork in /wallet/add → 400 (4) unrecognized chain → 400 (5) malformed chainNetwork (no hyphen) → 400 (6-7) missing/invalid chain in /wallet/create → 400 - docs: expand Jest lens in copilot-instructions.md + CLAUDE.md to require happy-path, edge-case, and missing-parameter coverage in every test suite
…r-compose to build locally
…panded tests
- Add OpenAPI lens and GitHub lens to CLAUDE.md and copilot-instructions.md (9 lenses total)
- Add src/templates/namespace/lfj-schema.json so Docker builds succeed
- Fix Swagger servers[0] to {url: '/'} so Try-it-out works at any port mapping
- Fix /wallet/balance description (remove internal lens reference)
- Expand test/wallet/wallet-balance.test.ts: +10 tests (chain-only, chainNetwork, error cases)
- Expand test/wallet/wallet-new-routes.test.ts: +18 tests (remove, setDefault, list wallets)
- Update pull_request.md to reflect all changes (86 tests, 5 suites)
Closed
13 tasks
Author
|
PR 1 of 3 from #638 |
Contributor
|
I'm not sure I understand why this is needed. The current wallet structure lets you create and add multiple wallets for Ethereum and for Solana. The Ethereum wallets can be used for any EVM network. |
Author
|
When I initially started working on the pancakeswap LPs I had hit a lot of issues with the route mapping bug for bsc, the bigint conversion errors and that most of the pancakeswap endpoints were commented out and must have noticed when I set my BSC=default it overwrote my eth.json file and must have assumed it was a bug at the time and hadn't revisited what it was actually resolving now that all the pancakeswap LP code was in place and working and it was just a part of the branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: Wallet Multi-Network Support (BSC + all EVM networks)
Branch:
feat-multichain-wallets→developmentSummary
Adds per-network wallet registration so the same EVM address can be tracked across
multiple networks (mainnet, BSC, Arbitrum, Base, etc.) without conflict. Introduces
a
/wallet/balanceendpoint, chain-singleton cache eviction, and BSC Swagger examplesacross all routes. All changes are backwards-compatible — no existing Hummingbot Python
strategies are affected.
Checklist
pnpm build)walletAddresses: string[]field unchanged (Hummingbot lens)fastify.httpErrors.*{encryptedKey, network}raw string) handled transparentlyservers[0]is{url: '/'}so "Try it out" works at any mapped portCLAUDE.mdand.github/copilot-instructions.mdkept in syncWhat Changed
1. Network-Aware Wallet Storage
Before: One wallet file per address, single
networkstring, no cross-network tracking.After: Same wallet file,
networks: string[]array, primary network atnetworks[0].Registering the same address for a new network merges the entry rather than overwriting it.
Files affected:
src/wallet/utils.ts—addWallet,createWallet,readWalletFileData,getWalletssrc/wallet/schemas.ts—WalletEntrySchemagainsnetworks[];AddWalletRequestSchemachainmade Optional withchainNetworkas alternative; handler-level guard requiresat least one of the two (throws
400if both omitted)2. New
/wallet/balanceEndpointPOST /wallet/balance— returns token balances for any address without requiringthe wallet to be registered.
Network resolution:
network/chainNetworkis provided — use it directly.mainnet(Ethereum) ormainnet-beta(Solana).Files affected:
src/wallet/routes/balance.ts,src/wallet/wallet.routes.ts3. Chain Singleton Cache Eviction
Ethereum.resetInstance(network)andSolana.resetInstance(network)evict acached provider so the next call to
getInstance()picks up the updatednodeURLwithout a server restart.
POST /config/updatenow callsresetInstanceautomatically whennodeURLchangesfor either chain.
Files affected:
src/chains/ethereum/ethereum.ts,src/chains/solana/solana.ts,src/config/routes/updateConfig.ts4.
chainNetworkShorthand Across All Wallet RoutesAll wallet routes (
/add,/create,/balance,/hardware/add) now acceptchainNetwork: "ethereum-bsc"as an alternative to supplyingchain+networkseparately. Parsing rule:
parts = value.split('-'); chain = parts[0]; network = parts.slice(1).join('-').5. BSC Swagger Documentation + Relative Server URL
All EVM
networkfield examples now include BSC alongside mainnet:All
chainNetworkexamples putethereum-bscimmediately afterethereum-mainnet:servers[0]in the OpenAPI spec is{url: '/'}so Swagger UI "Try it out" sendsrequests relative to whatever host/port it is served from, eliminating CORS errors
when the container is mapped to a non-default port.
Files affected:
src/app.ts,src/schemas/amm-schema.ts,src/schemas/clmm-schema.ts,src/schemas/chain-schema.ts,src/tokens/schemas.ts,src/pools/schemas.ts6.
chainNetworkRouting InfrastructurepoolInforoutes for both Uniswap and PancakeSwap now parsechainNetworkat thehandler level, enabling the same connector endpoint to serve multiple EVM networks.
Files affected:
src/connectors/uniswap/amm-routes/poolInfo.ts,src/connectors/uniswap/clmm-routes/poolInfo.ts,src/connectors/pancakeswap/amm-routes/poolInfo.ts,src/connectors/pancakeswap/clmm-routes/poolInfo.ts7. Corrupt Wallet File Warning
getWalletspreviously swallowed read errors silently. It now emitslogger.warnwith the file path and reason, then defaults to the chain's primary network, so
operators are notified of potentially misrouted wallets.
Backwards Compatibility
walletAddresses: string[]in GET /wallet response{encryptedKey, network}file format/wallet/addcallers supplyingchainnetworkomittedwalletAddressesandaddressfields unchangedFiles Changed
Test Coverage
test/wallet/wallet-balance.test.ts(22 tests)Happy paths
networknetwork: bscchainNetwork: ethereum-bscmainnet-betachainNetwork: solana-mainnet-betatokens[]array forwarded correctly to chaingetBalancestimestampis within current execution windowchain + addressonly (nonetwork) → defaults tomainnetautomaticallychain=solana + addressonly → defaults tomainnet-betaautomaticallychainNetwork: ethereum-mainnet→ resolvesnetworktomainnetEdge cases
networkMissing / invalid parameters
address→ 400chainandchainNetwork→ 400chain: bitcoin(unrecognized) → 400chainNetwork: ethereummainnet(no hyphen) → 400test/wallet/wallet-new-routes.test.ts(34 tests)POST /wallet/create (5 tests)
0xaddresssetDefault: trueaccepted without errorchain: invalid-chain→ 400POST /wallet/show-private-key (6 tests)
POST /wallet/send (7 tests)
token: 'SOL'DELETE /wallet/remove (6 tests)
POST /wallet/setDefault (5 tests)
GET /wallet/ (2 tests)
walletAddresses: []on every chain entrywalletAddressesis alwaysstring[]— never objectsIntegration (1 test)
test/wallet/wallet-multinetwork.test.ts(12 tests)networksmerges correctlywalletDetailsentry containsnetworks: ['mainnet', 'bsc']in registration orderwalletAddresses(backwards-compat string[]) contains address exactly once{encryptedKey, network}file reads and converts tonetworks: ['mainnet']['mainnet']hardwareWalletDetailswith correctnetworkstest/wallet/wallet-network-support.test.ts(18 tests)Happy paths — BSC stored,
chainNetworkparsed,solana-mainnet-betamulti-hyphen,chainNetworkoverridesnetwork, defaults tomainnet/mainnet-betaEdge cases — Corrupt wallet file →
logger.warn, address-format filteringMissing / invalid — No chain + no chainNetwork → 400,
chain: bitcoin→ 400,chainNetwork: ethereummainnet→ 400, missingprivateKey→ 400,empty
/wallet/createbody → 400,chain: tron→ 400Developer Testing
Start gateway (dev / HTTP mode)
Swagger UI
Open http://localhost:15888/docs — all wallet routes are under the
/wallettag."Try it out" works correctly because
servers[0]is the relative URL"/".Add wallet to BSC
Add same wallet to Ethereum mainnet (network merge)
Verify both networks are stored
Check balance (network auto-resolved from wallet store)
Verify 400 on missing chain
QA Tips
network,chainNetwork, and omitted (auto-detect).verify GET
/wallet/still lists it under the correct chain.chmod 000the.jsonfile and call GET/wallet/—a
WARNline should appear inlogs/and the address should still be listed withthe chain default network.
mainnetandbsc, then call GET/wallet/andconfirm the address appears once in
walletAddressesand once inwalletDetailswith
networks: ["mainnet","bsc"].walletAddressesis alwaysstring[](never objects) — this is the fieldHummingbot Python strategies consume.
{"chain":"ethereum","address":"0xYourAddress"}for/wallet/balance—networkis optional and defaults tomainnet.