[BCN] Multi Provider With Alchemy Adapter#4111
[BCN] Multi Provider With Alchemy Adapter#4111leolambo wants to merge 13 commits intobitpay:masterfrom
Conversation
Replace the circuit breaker state machine with a simpler consecutive-failure counter and cooldown approach. N failures in a row, skip for M seconds, then retry.
- Fix getBlockBeforeTime signature to match GetBlockBeforeTimeParams - Fix AlchemyAssetTransferStream field collision with base class - Fix blockHeight possibly undefined in confirmation - Remove unused imports and dead code - Cast test args as any to satisfy type constraints - Add operational logging to csp.ts (stream lifecycle, failover events, block-by-date resolution) - Rename _enforceFloorSemantics to _verifyBlockBeforeDate
- Rename IProviderConfig to IMultiProviderConfig with only health/priority/timeout fields - Move apiKey to global config.externalProviders.alchemy (matches Moralis pattern) - Resolve Alchemy URLs dynamically per-call via ALCHEMY_NETWORK_MAP - Add chain/network to AdapterBlockByDateParams for dynamic URL resolution - Add blockAtTimeCache (LRU per chain:network) to multi-provider CSP - Rename isBreakerable to affectsHealth across error taxonomy - Update all tests (47 passing)
kajoseph
left a comment
There was a problem hiding this comment.
Lots of lint errors, particularly with imports. Make sure you have the eslint extension installed and you may need to clear all your node_modules:
npx lerna exec rm -rf node_modules
Still functionally testing, but so far this is looking good!
packages/bitcore-node/src/providers/chain-state/external/adapters/alchemy.ts
Outdated
Show resolved
Hide resolved
| mtSyncTipPad?: number; // Default: 100. Multi-threaded sync will sync up to latest block height minus mtSyncTipPad. MT syncing is blind to reorgs. This helps ensure reorgs are accounted for near the tip. | ||
| leanTransactionStorage?: boolean; // Removes data, abiType, internal and calls before saving a transaction to the databases | ||
| needsL1Fee?: boolean; // Does this chain require a layer-1 fee to be added to a transaction (e.g. OP-stack chains)? | ||
| externalProviders?: IMultiProviderConfig[]; |
There was a problem hiding this comment.
is this type correct? I added to my config per this file and am getting a startup error.
bitcore.config.json:
...
"MATIC": {
"mainnet": {
...
"externalProviders": [{
"name": "alchemy",
"priority": 0
}]error:
Unhandled Rejection at: Error: AlchemyAdapter: apiKey is required in config.externalProviders.alchemy
at new AlchemyAdapter (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/providers/chain-state/external/adapters/alchemy.ts:37:24)
at Function.createAdapter (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/providers/chain-state/external/adapters/factory.ts:18:12)
at /home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/api/csp.ts:62:35
at Array.map (<anonymous>)
at MultiProviderEVMStateProvider.initializeProviders (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/api/csp.ts:61:10)
at new MultiProviderEVMStateProvider (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/api/csp.ts:40:10)
at new MultiProviderModule (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/index.ts:22:17)
at ModuleManager.loadConfigured (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/index.ts:80:36)
at ClusteredApiWorker (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/workers/api.ts:34:11)
at Object.<anonymous> (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/workers/api.ts:66:21)
There was a problem hiding this comment.
Well, I updated my config to fix that error, but now it's giving me another.
bitcore.config.json:
...
"MATIC": {
"mainnet": {
...
"externalProviders": {
"alchemy": {
"apiKey": ""
}
}error:
Unhandled Rejection at: TypeError: externalProviders.map is not a function
at MultiProviderEVMStateProvider.initializeProviders (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/api/csp.ts:61:10)
at new MultiProviderEVMStateProvider (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/api/csp.ts:40:10)
at new MultiProviderModule (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/multiProvider/index.ts:22:17)
at ModuleManager.loadConfigured (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/modules/index.ts:80:36)
at ClusteredApiWorker (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/workers/api.ts:34:11)
at Object.<anonymous> (/home/kjoseph/dev/bitcore/packages/bitcore-node/src/workers/api.ts:66:21)
at Module._compile (node:internal/modules/cjs/loader:1730:14)
at Object..js (node:internal/modules/cjs/loader:1895:10)
at Module.load (node:internal/modules/cjs/loader:1465:32)
at Function._load (node:internal/modules/cjs/loader:1282:12)
I'm confused about how this externalProviders field is supposed to look. One error makes it seems like it's supposed to be a map, the other suggest an array.
There was a problem hiding this comment.
Nevermind - this was a lot of noise for nothing. I figured it out.
There was a problem hiding this comment.
If anything's to be taken away from this, it's that having a field named "externalProviders" in two different places in the config can be confusing - especially when they're both needed when using the multi provider. Just 2c
packages/bitcore-node/src/providers/chain-state/external/adapters/alchemy.ts
Show resolved
Hide resolved
packages/bitcore-node/src/providers/chain-state/external/adapters/alchemy.ts
Show resolved
Hide resolved
Separate per-network routing order from provider credentials. The externalProviders key at the config root now holds only API keys, while indexedProviderRouting defines the priority-ordered adapter list per network.
BigInt values from external providers can exceed Number.MAX_SAFE_INTEGER, losing precision when cast to number. Accept string alongside number in gasLimit, gasPrice, nonce, value, and transactionIndex to preserve full precision.
Replace static ALCHEMY_NETWORK_MAP with convention-based URL derivation so new chains need no code change. Return RPC quantity fields as BigInt strings to avoid IEEE 754 precision loss. Update test assertions accordingly.
Description
Add multi-provider external chain state adapter with Alchemy integration, enabling failover between multiple indexed API providers for EVM chains.
Follow-up:
Moralis Adapter, API streaming improvements, Integration tests
Changelog
IIndexedAPIAdapterinterface, config types, andAdapterFactoryAlchemyAdapterwith asset transfer streamisBreakerable→affectsHealth)Testing Notes
Checklist
BWCif modifying the bitcore-wallet-client package,CLIif modifying the bitcore-cli package, etc.)