Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tripolskypetr/wallet-manager/llms.txt
Use this file to discover all available pages before exploring further.
Why Dependency Injection?
Wallet Manager constructs its services through an inversion-of-control (IoC) container rather than having code callnew WalletPrivateService() directly.
This gives three practical benefits:
-
Decoupled construction. Service consumers declare what they need (a
symbol); the container decides how to build and wire it. Swapping the
Binance backend for a different exchange would only require changing the
provideregistrations — nothing that calls the services needs to change. -
Singleton lifecycle. Each service is constructed exactly once, no
matter how many places inject it. The
WalletPublicService’s innermemoize-based per-symbol runner and theWalletPrivateService’s TTL caches are shared state that must not be duplicated. -
Testability.
override(TYPES.walletPrivateService, () => mockService)replaces a real service with a test double without modifying any call site.
DI Dependencies
Wallet Manager’s IoC container is provided by a single package:| Package | Role |
|---|---|
di-kit | Core IoC container. Provides createActivator, which yields provide, inject, init, and override. |
DI Symbols (src/core/types.ts)
Every service is identified by a well-known Symbol. Using Symbol.for
(rather than Symbol()) produces a global registry symbol — two calls to
Symbol.for('walletPrivateService') in different modules return the
same symbol, making cross-module injection reliable.
TYPES is the single source of truth for DI keys. Both the provide
registration and every inject call reference TYPES.walletPrivateService
or TYPES.walletPublicService — never raw strings.
The di File (src/core/di.ts)
di.ts creates the activator (the DI container instance) and re-exports the
four functions that the rest of the codebase uses:
| Export | Purpose |
|---|---|
provide(symbol, factory) | Registers a factory function against a DI symbol. |
inject<T>(symbol) | Resolves the service bound to the symbol. |
init() | Runs the container’s startup sequence (calls init on every registered service that has one). |
override(symbol, factory) | Replaces a registration — useful in tests. |
"wallet" activator instance, so they
share a single service registry.
Service Registration (src/core/provide.ts)
provide.ts registers both services by calling provide with a zero-arg
factory:
new WalletPrivateService()
the first time someone resolves TYPES.walletPrivateService. Subsequent
calls to inject(TYPES.walletPrivateService) return the cached instance.
WalletPublicService itself calls inject(TYPES.walletPrivateService)
inside its constructor — the container resolves WalletPrivateService
first and passes the same instance every time, so both services share
the same cache and clear() state.Startup Wiring (src/index.ts)
index.ts is the entry point that ties everything together:
import "./core/provide"— must happen before anyinjectcall so the factories are registered first.inject<>()— resolves lazy service instances (construction is deferred untilinit()calls each service’sinitmethod).init()— triggers the startup hook onWalletPrivateService(thesingleshotinitmethod that starts the GC interval and validates the Binance API credentials).
Consuming the Library
You do not construct services manually. Importwallet from the build
output and get fully initialized, DI-wired instances:
wallet global is injected automatically: