@sip-protocol/sdk 0.7.2 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
- package/dist/browser.d.mts +10 -4
- package/dist/browser.d.ts +10 -4
- package/dist/browser.js +48874 -18336
- package/dist/browser.mjs +674 -48
- package/dist/chunk-4GRJ5MAW.mjs +152 -0
- package/dist/chunk-5D7A3L3W.mjs +717 -0
- package/dist/chunk-64AYA5F5.mjs +7834 -0
- package/dist/chunk-GMDGB22A.mjs +379 -0
- package/dist/chunk-I534WKN7.mjs +328 -0
- package/dist/chunk-IBZVA5Y7.mjs +1003 -0
- package/dist/chunk-PRRZAWJE.mjs +223 -0
- package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
- package/dist/chunk-YWGJ77A2.mjs +33806 -0
- package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
- package/dist/constants-LHAAUC2T.mjs +51 -0
- package/dist/dist-2OGQ7FED.mjs +3957 -0
- package/dist/dist-IFHPYLDX.mjs +254 -0
- package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
- package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
- package/dist/index-DXh2IGkz.d.ts +24681 -0
- package/dist/index-DeE1ZzA4.d.mts +24681 -0
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48676 -17318
- package/dist/index.mjs +583 -19
- package/dist/interface-Bf7w1PLW.d.mts +679 -0
- package/dist/interface-Bf7w1PLW.d.ts +679 -0
- package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
- package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
- package/dist/proofs/halo2.d.mts +151 -0
- package/dist/proofs/halo2.d.ts +151 -0
- package/dist/proofs/halo2.js +350 -0
- package/dist/proofs/halo2.mjs +11 -0
- package/dist/proofs/kimchi.d.mts +160 -0
- package/dist/proofs/kimchi.d.ts +160 -0
- package/dist/proofs/kimchi.js +431 -0
- package/dist/proofs/kimchi.mjs +13 -0
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +74 -18
- package/dist/proofs/noir.mjs +84 -24
- package/dist/solana-U3MEGU7W.mjs +280 -0
- package/dist/validity_proof-3POXLPNY.mjs +21 -0
- package/package.json +54 -21
- package/src/adapters/index.ts +41 -0
- package/src/adapters/jupiter.ts +571 -0
- package/src/adapters/near-intents.ts +135 -0
- package/src/advisor/advisor.ts +653 -0
- package/src/advisor/index.ts +54 -0
- package/src/advisor/tools.ts +303 -0
- package/src/advisor/types.ts +164 -0
- package/src/chains/ethereum/announcement.ts +536 -0
- package/src/chains/ethereum/bnb-optimizations.ts +474 -0
- package/src/chains/ethereum/commitment.ts +522 -0
- package/src/chains/ethereum/constants.ts +462 -0
- package/src/chains/ethereum/deployment.ts +596 -0
- package/src/chains/ethereum/gas-estimation.ts +538 -0
- package/src/chains/ethereum/index.ts +268 -0
- package/src/chains/ethereum/optimizations.ts +614 -0
- package/src/chains/ethereum/privacy-adapter.ts +855 -0
- package/src/chains/ethereum/registry.ts +584 -0
- package/src/chains/ethereum/rpc.ts +905 -0
- package/src/chains/ethereum/stealth.ts +491 -0
- package/src/chains/ethereum/token.ts +790 -0
- package/src/chains/ethereum/transfer.ts +637 -0
- package/src/chains/ethereum/types.ts +456 -0
- package/src/chains/ethereum/viewing-key.ts +455 -0
- package/src/chains/near/commitment.ts +608 -0
- package/src/chains/near/constants.ts +284 -0
- package/src/chains/near/function-call.ts +871 -0
- package/src/chains/near/history.ts +654 -0
- package/src/chains/near/implicit-account.ts +840 -0
- package/src/chains/near/index.ts +393 -0
- package/src/chains/near/native-transfer.ts +658 -0
- package/src/chains/near/nep141.ts +775 -0
- package/src/chains/near/privacy-adapter.ts +889 -0
- package/src/chains/near/resolver.ts +971 -0
- package/src/chains/near/rpc.ts +1016 -0
- package/src/chains/near/stealth.ts +419 -0
- package/src/chains/near/types.ts +317 -0
- package/src/chains/near/viewing-key.ts +876 -0
- package/src/chains/solana/anchor-transfer.ts +386 -0
- package/src/chains/solana/commitment.ts +577 -0
- package/src/chains/solana/constants.ts +126 -12
- package/src/chains/solana/ephemeral-keys.ts +543 -0
- package/src/chains/solana/index.ts +276 -1
- package/src/chains/solana/key-derivation.ts +418 -0
- package/src/chains/solana/kit-compat.ts +334 -0
- package/src/chains/solana/optimizations.ts +560 -0
- package/src/chains/solana/privacy-adapter.ts +605 -0
- package/src/chains/solana/providers/generic.ts +201 -0
- package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
- package/src/chains/solana/providers/helius-enhanced.ts +623 -0
- package/src/chains/solana/providers/helius.ts +402 -0
- package/src/chains/solana/providers/index.ts +85 -0
- package/src/chains/solana/providers/interface.ts +221 -0
- package/src/chains/solana/providers/quicknode.ts +409 -0
- package/src/chains/solana/providers/triton.ts +426 -0
- package/src/chains/solana/providers/webhook.ts +790 -0
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +170 -73
- package/src/chains/solana/sol-transfer.ts +732 -0
- package/src/chains/solana/spl-transfer.ts +886 -0
- package/src/chains/solana/stealth-scanner.ts +703 -0
- package/src/chains/solana/sunspot-verifier.ts +453 -0
- package/src/chains/solana/transaction-builder.ts +755 -0
- package/src/chains/solana/transfer.ts +74 -5
- package/src/chains/solana/types.ts +77 -7
- package/src/chains/solana/utils.ts +110 -0
- package/src/chains/solana/viewing-key.ts +807 -0
- package/src/compliance/fireblocks.ts +921 -0
- package/src/compliance/index.ts +37 -0
- package/src/compliance/range-sas.ts +956 -0
- package/src/config/endpoints.ts +100 -0
- package/src/crypto.ts +11 -8
- package/src/errors.ts +82 -0
- package/src/evm/erc4337-relayer.ts +830 -0
- package/src/evm/index.ts +47 -0
- package/src/fees/calculator.ts +396 -0
- package/src/fees/index.ts +87 -0
- package/src/fees/near-contract.ts +429 -0
- package/src/fees/types.ts +268 -0
- package/src/index.ts +785 -1
- package/src/intent.ts +6 -3
- package/src/logger.ts +324 -0
- package/src/network/index.ts +80 -0
- package/src/network/proxy.ts +691 -0
- package/src/optimizations/index.ts +541 -0
- package/src/oracle/types.ts +1 -0
- package/src/privacy-backends/arcium-types.ts +727 -0
- package/src/privacy-backends/arcium.ts +719 -0
- package/src/privacy-backends/combined-privacy.ts +866 -0
- package/src/privacy-backends/cspl-token.ts +595 -0
- package/src/privacy-backends/cspl-types.ts +512 -0
- package/src/privacy-backends/cspl.ts +907 -0
- package/src/privacy-backends/health.ts +488 -0
- package/src/privacy-backends/inco-types.ts +323 -0
- package/src/privacy-backends/inco.ts +616 -0
- package/src/privacy-backends/index.ts +336 -0
- package/src/privacy-backends/interface.ts +906 -0
- package/src/privacy-backends/lru-cache.ts +343 -0
- package/src/privacy-backends/magicblock.ts +458 -0
- package/src/privacy-backends/mock.ts +258 -0
- package/src/privacy-backends/privacycash-types.ts +278 -0
- package/src/privacy-backends/privacycash.ts +456 -0
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +690 -0
- package/src/privacy-backends/router.ts +626 -0
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +256 -0
- package/src/privacy-logger.ts +191 -0
- package/src/production-safety.ts +373 -0
- package/src/proofs/aggregator.ts +1029 -0
- package/src/proofs/browser-composer.ts +1150 -0
- package/src/proofs/browser.ts +113 -25
- package/src/proofs/cache/index.ts +127 -0
- package/src/proofs/cache/interface.ts +545 -0
- package/src/proofs/cache/key-generator.ts +188 -0
- package/src/proofs/cache/lru-cache.ts +481 -0
- package/src/proofs/cache/multi-tier-cache.ts +575 -0
- package/src/proofs/cache/persistent-cache.ts +788 -0
- package/src/proofs/compliance-proof.ts +872 -0
- package/src/proofs/composer/base.ts +923 -0
- package/src/proofs/composer/index.ts +25 -0
- package/src/proofs/composer/interface.ts +518 -0
- package/src/proofs/composer/types.ts +383 -0
- package/src/proofs/converters/halo2.ts +452 -0
- package/src/proofs/converters/index.ts +208 -0
- package/src/proofs/converters/interface.ts +363 -0
- package/src/proofs/converters/kimchi.ts +462 -0
- package/src/proofs/converters/noir.ts +451 -0
- package/src/proofs/fallback.ts +888 -0
- package/src/proofs/halo2.ts +42 -0
- package/src/proofs/index.ts +471 -0
- package/src/proofs/interface.ts +13 -0
- package/src/proofs/kimchi.ts +42 -0
- package/src/proofs/lazy.ts +1004 -0
- package/src/proofs/mock.ts +25 -1
- package/src/proofs/noir.ts +111 -30
- package/src/proofs/orchestrator.ts +960 -0
- package/src/proofs/parallel/concurrency.ts +297 -0
- package/src/proofs/parallel/dependency-graph.ts +602 -0
- package/src/proofs/parallel/executor.ts +420 -0
- package/src/proofs/parallel/index.ts +131 -0
- package/src/proofs/parallel/interface.ts +685 -0
- package/src/proofs/parallel/worker-pool.ts +644 -0
- package/src/proofs/providers/halo2.ts +560 -0
- package/src/proofs/providers/index.ts +34 -0
- package/src/proofs/providers/kimchi.ts +641 -0
- package/src/proofs/validator.ts +881 -0
- package/src/proofs/verifier.ts +867 -0
- package/src/quantum/index.ts +112 -0
- package/src/quantum/winternitz-vault.ts +639 -0
- package/src/quantum/wots.ts +611 -0
- package/src/settlement/backends/direct-chain.ts +1 -0
- package/src/settlement/index.ts +9 -0
- package/src/settlement/router.ts +732 -46
- package/src/solana/index.ts +72 -0
- package/src/solana/jito-relayer.ts +687 -0
- package/src/solana/noir-verifier-types.ts +430 -0
- package/src/solana/noir-verifier.ts +816 -0
- package/src/stealth/address-derivation.ts +193 -0
- package/src/stealth/ed25519.ts +431 -0
- package/src/stealth/index.ts +233 -0
- package/src/stealth/meta-address.ts +221 -0
- package/src/stealth/secp256k1.ts +368 -0
- package/src/stealth/utils.ts +194 -0
- package/src/stealth.ts +50 -1504
- package/src/surveillance/algorithms/address-reuse.ts +143 -0
- package/src/surveillance/algorithms/cluster.ts +247 -0
- package/src/surveillance/algorithms/exchange.ts +295 -0
- package/src/surveillance/algorithms/temporal.ts +337 -0
- package/src/surveillance/analyzer.ts +442 -0
- package/src/surveillance/index.ts +64 -0
- package/src/surveillance/scoring.ts +372 -0
- package/src/surveillance/types.ts +264 -0
- package/src/sync/index.ts +106 -0
- package/src/sync/manager.ts +504 -0
- package/src/sync/mock-provider.ts +318 -0
- package/src/sync/oblivious.ts +625 -0
- package/src/tokens/index.ts +15 -0
- package/src/tokens/registry.ts +301 -0
- package/src/utils/deprecation.ts +94 -0
- package/src/utils/index.ts +9 -0
- package/src/wallet/ethereum/index.ts +68 -0
- package/src/wallet/ethereum/metamask-privacy.ts +420 -0
- package/src/wallet/ethereum/multi-wallet.ts +646 -0
- package/src/wallet/ethereum/privacy-adapter.ts +700 -0
- package/src/wallet/ethereum/types.ts +3 -1
- package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
- package/src/wallet/hardware/index.ts +10 -0
- package/src/wallet/hardware/ledger-privacy.ts +414 -0
- package/src/wallet/index.ts +71 -0
- package/src/wallet/near/adapter.ts +626 -0
- package/src/wallet/near/index.ts +86 -0
- package/src/wallet/near/meteor-wallet.ts +1153 -0
- package/src/wallet/near/my-near-wallet.ts +790 -0
- package/src/wallet/near/wallet-selector.ts +702 -0
- package/src/wallet/solana/adapter.ts +6 -4
- package/src/wallet/solana/index.ts +13 -0
- package/src/wallet/solana/privacy-adapter.ts +567 -0
- package/src/wallet/sui/types.ts +6 -4
- package/src/zcash/rpc-client.ts +13 -6
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-BYZbDjal.d.ts +0 -11390
- package/dist/index-CHB3KuOB.d.mts +0 -11859
- package/dist/index-CzWPI6Le.d.ts +0 -11859
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-Q4NAVBTS.mjs +0 -46
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Backend Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages registration and discovery of privacy backends.
|
|
5
|
+
* Optionally integrates with BackendHealthTracker for circuit breaker support.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const registry = new PrivacyBackendRegistry()
|
|
10
|
+
*
|
|
11
|
+
* // Register backends
|
|
12
|
+
* registry.register(new SIPNativeBackend())
|
|
13
|
+
* registry.register(new PrivacyCashBackend(), { priority: 10 })
|
|
14
|
+
*
|
|
15
|
+
* // Get backends
|
|
16
|
+
* const all = registry.getAll()
|
|
17
|
+
* const byName = registry.get('sip-native')
|
|
18
|
+
* const forChain = registry.getByChain('solana')
|
|
19
|
+
* const forType = registry.getByType('transaction')
|
|
20
|
+
*
|
|
21
|
+
* // Health-aware operations (when health tracker is attached)
|
|
22
|
+
* const healthy = registry.getHealthy()
|
|
23
|
+
* const health = registry.getHealthState('sip-native')
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type { ChainType } from '@sip-protocol/types'
|
|
28
|
+
import type {
|
|
29
|
+
PrivacyBackend,
|
|
30
|
+
BackendType,
|
|
31
|
+
BackendRegistrationOptions,
|
|
32
|
+
RegisteredBackend,
|
|
33
|
+
TransferParams,
|
|
34
|
+
AvailabilityResult,
|
|
35
|
+
BackendHealthState,
|
|
36
|
+
BackendMetrics,
|
|
37
|
+
CircuitBreakerConfig,
|
|
38
|
+
} from './interface'
|
|
39
|
+
import { warnIfDeprecatedVersion } from './interface'
|
|
40
|
+
import { BackendHealthTracker } from './health'
|
|
41
|
+
import { RateLimiter, type RateLimiterConfig, type RateLimitStats, type AcquireOptions } from './rate-limiter'
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Default priority for registered backends
|
|
45
|
+
*/
|
|
46
|
+
const DEFAULT_PRIORITY = 50
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Registry configuration options
|
|
50
|
+
*/
|
|
51
|
+
export interface PrivacyBackendRegistryConfig {
|
|
52
|
+
/**
|
|
53
|
+
* Enable health tracking with circuit breaker
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
enableHealthTracking?: boolean
|
|
57
|
+
/**
|
|
58
|
+
* Circuit breaker configuration (when health tracking is enabled)
|
|
59
|
+
*/
|
|
60
|
+
circuitBreakerConfig?: Partial<CircuitBreakerConfig>
|
|
61
|
+
/**
|
|
62
|
+
* Enable rate limiting for backends
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
enableRateLimiting?: boolean
|
|
66
|
+
/**
|
|
67
|
+
* Rate limiter configuration (when rate limiting is enabled)
|
|
68
|
+
*/
|
|
69
|
+
rateLimiterConfig?: RateLimiterConfig
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Registry for managing privacy backends
|
|
74
|
+
*
|
|
75
|
+
* Provides a centralized way to register, discover, and manage
|
|
76
|
+
* different privacy backend implementations. Optionally integrates
|
|
77
|
+
* with BackendHealthTracker for circuit breaker support.
|
|
78
|
+
*/
|
|
79
|
+
export class PrivacyBackendRegistry {
|
|
80
|
+
private backends: Map<string, RegisteredBackend> = new Map()
|
|
81
|
+
private healthTracker: BackendHealthTracker | null = null
|
|
82
|
+
private rateLimiter: RateLimiter | null = null
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Create a new registry
|
|
86
|
+
*
|
|
87
|
+
* @param config - Registry configuration
|
|
88
|
+
*/
|
|
89
|
+
constructor(config: PrivacyBackendRegistryConfig = {}) {
|
|
90
|
+
const {
|
|
91
|
+
enableHealthTracking = true,
|
|
92
|
+
circuitBreakerConfig,
|
|
93
|
+
enableRateLimiting = false,
|
|
94
|
+
rateLimiterConfig,
|
|
95
|
+
} = config
|
|
96
|
+
|
|
97
|
+
if (enableHealthTracking) {
|
|
98
|
+
this.healthTracker = new BackendHealthTracker(circuitBreakerConfig)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (enableRateLimiting) {
|
|
102
|
+
this.rateLimiter = new RateLimiter(rateLimiterConfig)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the health tracker instance
|
|
108
|
+
*
|
|
109
|
+
* @returns Health tracker or null if not enabled
|
|
110
|
+
*/
|
|
111
|
+
getHealthTracker(): BackendHealthTracker | null {
|
|
112
|
+
return this.healthTracker
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Attach an external health tracker
|
|
117
|
+
*
|
|
118
|
+
* Useful for sharing a health tracker between multiple registries
|
|
119
|
+
* or for testing.
|
|
120
|
+
*
|
|
121
|
+
* @param tracker - Health tracker to attach
|
|
122
|
+
*/
|
|
123
|
+
setHealthTracker(tracker: BackendHealthTracker | null): void {
|
|
124
|
+
this.healthTracker = tracker
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get the rate limiter instance
|
|
129
|
+
*
|
|
130
|
+
* @returns Rate limiter or null if not enabled
|
|
131
|
+
*/
|
|
132
|
+
getRateLimiter(): RateLimiter | null {
|
|
133
|
+
return this.rateLimiter
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Attach an external rate limiter
|
|
138
|
+
*
|
|
139
|
+
* Useful for sharing a rate limiter between multiple registries
|
|
140
|
+
* or for testing.
|
|
141
|
+
*
|
|
142
|
+
* @param limiter - Rate limiter to attach
|
|
143
|
+
*/
|
|
144
|
+
setRateLimiter(limiter: RateLimiter | null): void {
|
|
145
|
+
this.rateLimiter = limiter
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Register a privacy backend
|
|
150
|
+
*
|
|
151
|
+
* @param backend - Backend instance to register
|
|
152
|
+
* @param options - Registration options
|
|
153
|
+
* @throws Error if backend with same name exists and override is false
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* registry.register(new SIPNativeBackend())
|
|
158
|
+
* registry.register(new PrivacyCashBackend(), { priority: 100 })
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
register(
|
|
162
|
+
backend: PrivacyBackend,
|
|
163
|
+
options: BackendRegistrationOptions = {}
|
|
164
|
+
): void {
|
|
165
|
+
const { override = false, priority = DEFAULT_PRIORITY, enabled = true } = options
|
|
166
|
+
|
|
167
|
+
if (this.backends.has(backend.name) && !override) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Backend '${backend.name}' is already registered. ` +
|
|
170
|
+
`Use { override: true } to replace it.`
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Warn about deprecated interface versions
|
|
175
|
+
warnIfDeprecatedVersion(backend)
|
|
176
|
+
|
|
177
|
+
this.backends.set(backend.name, {
|
|
178
|
+
backend,
|
|
179
|
+
priority,
|
|
180
|
+
enabled,
|
|
181
|
+
registeredAt: Date.now(),
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// Register with health tracker if enabled
|
|
185
|
+
if (this.healthTracker) {
|
|
186
|
+
this.healthTracker.register(backend.name)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Unregister a backend by name
|
|
192
|
+
*
|
|
193
|
+
* @param name - Backend name to unregister
|
|
194
|
+
* @returns true if backend was removed, false if not found
|
|
195
|
+
*/
|
|
196
|
+
unregister(name: string): boolean {
|
|
197
|
+
const removed = this.backends.delete(name)
|
|
198
|
+
if (removed && this.healthTracker) {
|
|
199
|
+
this.healthTracker.unregister(name)
|
|
200
|
+
}
|
|
201
|
+
return removed
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Get a backend by name
|
|
206
|
+
*
|
|
207
|
+
* @param name - Backend name
|
|
208
|
+
* @returns Backend instance or undefined if not found
|
|
209
|
+
*/
|
|
210
|
+
get(name: string): PrivacyBackend | undefined {
|
|
211
|
+
const entry = this.backends.get(name)
|
|
212
|
+
return entry?.enabled ? entry.backend : undefined
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Check if a backend is registered
|
|
217
|
+
*
|
|
218
|
+
* @param name - Backend name
|
|
219
|
+
* @returns true if registered (regardless of enabled state)
|
|
220
|
+
*/
|
|
221
|
+
has(name: string): boolean {
|
|
222
|
+
return this.backends.has(name)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get all enabled backends sorted by priority
|
|
227
|
+
*
|
|
228
|
+
* @returns Array of backends (highest priority first)
|
|
229
|
+
*/
|
|
230
|
+
getAll(): PrivacyBackend[] {
|
|
231
|
+
return Array.from(this.backends.values())
|
|
232
|
+
.filter(entry => entry.enabled)
|
|
233
|
+
.sort((a, b) => b.priority - a.priority)
|
|
234
|
+
.map(entry => entry.backend)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get all registered entries (including disabled)
|
|
239
|
+
*
|
|
240
|
+
* @returns Array of registered backend entries
|
|
241
|
+
*/
|
|
242
|
+
getAllEntries(): RegisteredBackend[] {
|
|
243
|
+
return Array.from(this.backends.values())
|
|
244
|
+
.sort((a, b) => b.priority - a.priority)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get backends supporting a specific chain
|
|
249
|
+
*
|
|
250
|
+
* @param chain - Chain type to filter by
|
|
251
|
+
* @returns Array of backends supporting the chain
|
|
252
|
+
*/
|
|
253
|
+
getByChain(chain: ChainType): PrivacyBackend[] {
|
|
254
|
+
return this.getAll().filter(backend =>
|
|
255
|
+
backend.chains.includes(chain)
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get backends of a specific type
|
|
261
|
+
*
|
|
262
|
+
* @param type - Backend type to filter by
|
|
263
|
+
* @returns Array of backends of the specified type
|
|
264
|
+
*/
|
|
265
|
+
getByType(type: BackendType): PrivacyBackend[] {
|
|
266
|
+
return this.getAll().filter(backend =>
|
|
267
|
+
backend.type === type || backend.type === 'both'
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get backends that support compliance (viewing keys)
|
|
273
|
+
*
|
|
274
|
+
* @returns Array of compliance-supporting backends
|
|
275
|
+
*/
|
|
276
|
+
getCompliant(): PrivacyBackend[] {
|
|
277
|
+
return this.getAll().filter(backend =>
|
|
278
|
+
backend.getCapabilities().complianceSupport
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Find available backends for a transfer
|
|
284
|
+
*
|
|
285
|
+
* @param params - Transfer parameters
|
|
286
|
+
* @returns Array of available backends with availability info
|
|
287
|
+
*/
|
|
288
|
+
async findAvailable(
|
|
289
|
+
params: TransferParams
|
|
290
|
+
): Promise<Array<{ backend: PrivacyBackend; availability: AvailabilityResult }>> {
|
|
291
|
+
const chainBackends = this.getByChain(params.chain)
|
|
292
|
+
const results: Array<{ backend: PrivacyBackend; availability: AvailabilityResult }> = []
|
|
293
|
+
|
|
294
|
+
for (const backend of chainBackends) {
|
|
295
|
+
const availability = await backend.checkAvailability(params)
|
|
296
|
+
if (availability.available) {
|
|
297
|
+
results.push({ backend, availability })
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return results
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Enable a backend
|
|
306
|
+
*
|
|
307
|
+
* @param name - Backend name
|
|
308
|
+
* @returns true if backend was enabled, false if not found
|
|
309
|
+
*/
|
|
310
|
+
enable(name: string): boolean {
|
|
311
|
+
const entry = this.backends.get(name)
|
|
312
|
+
if (entry) {
|
|
313
|
+
entry.enabled = true
|
|
314
|
+
return true
|
|
315
|
+
}
|
|
316
|
+
return false
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Disable a backend
|
|
321
|
+
*
|
|
322
|
+
* @param name - Backend name
|
|
323
|
+
* @returns true if backend was disabled, false if not found
|
|
324
|
+
*/
|
|
325
|
+
disable(name: string): boolean {
|
|
326
|
+
const entry = this.backends.get(name)
|
|
327
|
+
if (entry) {
|
|
328
|
+
entry.enabled = false
|
|
329
|
+
return true
|
|
330
|
+
}
|
|
331
|
+
return false
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Set backend priority
|
|
336
|
+
*
|
|
337
|
+
* @param name - Backend name
|
|
338
|
+
* @param priority - New priority value
|
|
339
|
+
* @returns true if priority was set, false if not found
|
|
340
|
+
*/
|
|
341
|
+
setPriority(name: string, priority: number): boolean {
|
|
342
|
+
const entry = this.backends.get(name)
|
|
343
|
+
if (entry) {
|
|
344
|
+
entry.priority = priority
|
|
345
|
+
return true
|
|
346
|
+
}
|
|
347
|
+
return false
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Get count of registered backends
|
|
352
|
+
*
|
|
353
|
+
* @param enabledOnly - If true, only count enabled backends
|
|
354
|
+
* @returns Number of backends
|
|
355
|
+
*/
|
|
356
|
+
count(enabledOnly: boolean = false): number {
|
|
357
|
+
if (enabledOnly) {
|
|
358
|
+
return Array.from(this.backends.values()).filter(e => e.enabled).length
|
|
359
|
+
}
|
|
360
|
+
return this.backends.size
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Clear all registered backends
|
|
365
|
+
*/
|
|
366
|
+
clear(): void {
|
|
367
|
+
this.backends.clear()
|
|
368
|
+
if (this.healthTracker) {
|
|
369
|
+
this.healthTracker.clear()
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Get backend names
|
|
375
|
+
*
|
|
376
|
+
* @param enabledOnly - If true, only return enabled backend names
|
|
377
|
+
* @returns Array of backend names
|
|
378
|
+
*/
|
|
379
|
+
getNames(enabledOnly: boolean = false): string[] {
|
|
380
|
+
if (enabledOnly) {
|
|
381
|
+
return Array.from(this.backends.entries())
|
|
382
|
+
.filter(([, entry]) => entry.enabled)
|
|
383
|
+
.map(([name]) => name)
|
|
384
|
+
}
|
|
385
|
+
return Array.from(this.backends.keys())
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ─── Health-Aware Methods ───────────────────────────────────────────────────
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get all healthy backends (circuit not open)
|
|
392
|
+
*
|
|
393
|
+
* Filters out backends where the circuit breaker is open.
|
|
394
|
+
* Falls back to getAll() if health tracking is disabled.
|
|
395
|
+
*
|
|
396
|
+
* @returns Array of healthy backends
|
|
397
|
+
*/
|
|
398
|
+
getHealthy(): PrivacyBackend[] {
|
|
399
|
+
const all = this.getAll()
|
|
400
|
+
if (!this.healthTracker) {
|
|
401
|
+
return all
|
|
402
|
+
}
|
|
403
|
+
return all.filter(backend => this.healthTracker!.isHealthy(backend.name))
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Get healthy backends supporting a specific chain
|
|
408
|
+
*
|
|
409
|
+
* @param chain - Chain type to filter by
|
|
410
|
+
* @returns Array of healthy backends supporting the chain
|
|
411
|
+
*/
|
|
412
|
+
getHealthyByChain(chain: ChainType): PrivacyBackend[] {
|
|
413
|
+
return this.getHealthy().filter(backend => backend.chains.includes(chain))
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Get health state for a backend
|
|
418
|
+
*
|
|
419
|
+
* @param name - Backend name
|
|
420
|
+
* @returns Health state or undefined if not tracked
|
|
421
|
+
*/
|
|
422
|
+
getHealthState(name: string): BackendHealthState | undefined {
|
|
423
|
+
return this.healthTracker?.getHealth(name)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Get metrics for a backend
|
|
428
|
+
*
|
|
429
|
+
* @param name - Backend name
|
|
430
|
+
* @returns Metrics or undefined if not tracked
|
|
431
|
+
*/
|
|
432
|
+
getMetrics(name: string): BackendMetrics | undefined {
|
|
433
|
+
return this.healthTracker?.getMetrics(name)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Get summary of all backend health
|
|
438
|
+
*
|
|
439
|
+
* @returns Object with backend names as keys and health info as values
|
|
440
|
+
*/
|
|
441
|
+
getHealthSummary(): Record<string, {
|
|
442
|
+
healthy: boolean
|
|
443
|
+
state: string
|
|
444
|
+
failures: number
|
|
445
|
+
lastError?: string
|
|
446
|
+
}> {
|
|
447
|
+
if (!this.healthTracker) {
|
|
448
|
+
// Return all backends as healthy when tracking is disabled
|
|
449
|
+
const summary: Record<string, {
|
|
450
|
+
healthy: boolean
|
|
451
|
+
state: string
|
|
452
|
+
failures: number
|
|
453
|
+
}> = {}
|
|
454
|
+
for (const name of this.getNames()) {
|
|
455
|
+
summary[name] = { healthy: true, state: 'closed', failures: 0 }
|
|
456
|
+
}
|
|
457
|
+
return summary
|
|
458
|
+
}
|
|
459
|
+
return this.healthTracker.getHealthSummary()
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Check if a backend is healthy
|
|
464
|
+
*
|
|
465
|
+
* @param name - Backend name
|
|
466
|
+
* @returns true if healthy or health tracking is disabled
|
|
467
|
+
*/
|
|
468
|
+
isHealthy(name: string): boolean {
|
|
469
|
+
if (!this.healthTracker) {
|
|
470
|
+
return true
|
|
471
|
+
}
|
|
472
|
+
return this.healthTracker.isHealthy(name)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Manually open circuit for a backend
|
|
477
|
+
*
|
|
478
|
+
* Useful for maintenance or known issues.
|
|
479
|
+
*
|
|
480
|
+
* @param name - Backend name
|
|
481
|
+
* @returns true if circuit was opened, false if not found or tracking disabled
|
|
482
|
+
*/
|
|
483
|
+
openCircuit(name: string): boolean {
|
|
484
|
+
if (!this.healthTracker || !this.backends.has(name)) {
|
|
485
|
+
return false
|
|
486
|
+
}
|
|
487
|
+
this.healthTracker.forceOpen(name)
|
|
488
|
+
return true
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Manually close circuit for a backend
|
|
493
|
+
*
|
|
494
|
+
* Use with caution - may route requests to failing backend.
|
|
495
|
+
*
|
|
496
|
+
* @param name - Backend name
|
|
497
|
+
* @returns true if circuit was closed, false if not found or tracking disabled
|
|
498
|
+
*/
|
|
499
|
+
closeCircuit(name: string): boolean {
|
|
500
|
+
if (!this.healthTracker || !this.backends.has(name)) {
|
|
501
|
+
return false
|
|
502
|
+
}
|
|
503
|
+
this.healthTracker.forceClose(name)
|
|
504
|
+
return true
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Reset health state for a backend
|
|
509
|
+
*
|
|
510
|
+
* Clears failure count and closes circuit.
|
|
511
|
+
*
|
|
512
|
+
* @param name - Backend name
|
|
513
|
+
* @returns true if reset, false if not found or tracking disabled
|
|
514
|
+
*/
|
|
515
|
+
resetHealth(name: string): boolean {
|
|
516
|
+
if (!this.healthTracker || !this.backends.has(name)) {
|
|
517
|
+
return false
|
|
518
|
+
}
|
|
519
|
+
this.healthTracker.reset(name)
|
|
520
|
+
return true
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Record a successful execution for a backend
|
|
525
|
+
*
|
|
526
|
+
* @param name - Backend name
|
|
527
|
+
* @param latencyMs - Request latency in milliseconds
|
|
528
|
+
*/
|
|
529
|
+
recordSuccess(name: string, latencyMs: number): void {
|
|
530
|
+
if (this.healthTracker) {
|
|
531
|
+
this.healthTracker.recordSuccess(name, latencyMs)
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Record a failed execution for a backend
|
|
537
|
+
*
|
|
538
|
+
* @param name - Backend name
|
|
539
|
+
* @param reason - Failure reason
|
|
540
|
+
*/
|
|
541
|
+
recordFailure(name: string, reason: string): void {
|
|
542
|
+
if (this.healthTracker) {
|
|
543
|
+
this.healthTracker.recordFailure(name, reason)
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// ─── Rate Limiting Methods ─────────────────────────────────────────────────
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Try to acquire rate limit tokens for a backend (non-blocking)
|
|
551
|
+
*
|
|
552
|
+
* @param name - Backend name
|
|
553
|
+
* @param tokens - Number of tokens to acquire (default: 1)
|
|
554
|
+
* @returns true if tokens were acquired, false if rate limited or limiter disabled
|
|
555
|
+
*/
|
|
556
|
+
tryAcquire(name: string, tokens: number = 1): boolean {
|
|
557
|
+
if (!this.rateLimiter) {
|
|
558
|
+
return true // No rate limiting enabled
|
|
559
|
+
}
|
|
560
|
+
return this.rateLimiter.tryAcquire(name, tokens)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Acquire rate limit tokens for a backend (async with queueing)
|
|
565
|
+
*
|
|
566
|
+
* @param name - Backend name
|
|
567
|
+
* @param options - Acquire options (tokens, timeout)
|
|
568
|
+
* @returns Promise resolving when tokens are acquired
|
|
569
|
+
* @throws RateLimitExceededError, QueueFullError, or AcquireTimeoutError
|
|
570
|
+
*/
|
|
571
|
+
async acquire(name: string, options?: AcquireOptions): Promise<void> {
|
|
572
|
+
if (!this.rateLimiter) {
|
|
573
|
+
return // No rate limiting enabled
|
|
574
|
+
}
|
|
575
|
+
await this.rateLimiter.acquire(name, options)
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Check if tokens can be acquired without consuming them
|
|
580
|
+
*
|
|
581
|
+
* @param name - Backend name
|
|
582
|
+
* @param tokens - Number of tokens to check (default: 1)
|
|
583
|
+
* @returns true if tokens are available
|
|
584
|
+
*/
|
|
585
|
+
canAcquire(name: string, tokens: number = 1): boolean {
|
|
586
|
+
if (!this.rateLimiter) {
|
|
587
|
+
return true // No rate limiting enabled
|
|
588
|
+
}
|
|
589
|
+
return this.rateLimiter.canAcquire(name, tokens)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get rate limit statistics for a backend
|
|
594
|
+
*
|
|
595
|
+
* @param name - Backend name
|
|
596
|
+
* @returns Rate limit stats or undefined if limiter disabled
|
|
597
|
+
*/
|
|
598
|
+
getRateLimitStats(name: string): RateLimitStats | undefined {
|
|
599
|
+
return this.rateLimiter?.getStats(name)
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Check if a backend is rate limited (no tokens available)
|
|
604
|
+
*
|
|
605
|
+
* @param name - Backend name
|
|
606
|
+
* @returns true if rate limited, false if available or limiter disabled
|
|
607
|
+
*/
|
|
608
|
+
isRateLimited(name: string): boolean {
|
|
609
|
+
if (!this.rateLimiter) {
|
|
610
|
+
return false
|
|
611
|
+
}
|
|
612
|
+
return !this.rateLimiter.canAcquire(name)
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Get all backends that are NOT rate limited
|
|
617
|
+
*
|
|
618
|
+
* @returns Array of backends with available rate limit tokens
|
|
619
|
+
*/
|
|
620
|
+
getAvailable(): PrivacyBackend[] {
|
|
621
|
+
const all = this.getAll()
|
|
622
|
+
if (!this.rateLimiter) {
|
|
623
|
+
return all
|
|
624
|
+
}
|
|
625
|
+
return all.filter(backend => this.rateLimiter!.canAcquire(backend.name))
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Get available backends for a specific chain
|
|
630
|
+
*
|
|
631
|
+
* Filters by both chain support and rate limit availability.
|
|
632
|
+
*
|
|
633
|
+
* @param chain - Chain type to filter by
|
|
634
|
+
* @returns Array of available backends supporting the chain
|
|
635
|
+
*/
|
|
636
|
+
getAvailableByChain(chain: ChainType): PrivacyBackend[] {
|
|
637
|
+
return this.getAvailable().filter(backend => backend.chains.includes(chain))
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Get backends that are both healthy AND not rate limited
|
|
642
|
+
*
|
|
643
|
+
* @returns Array of backends ready for use
|
|
644
|
+
*/
|
|
645
|
+
getReady(): PrivacyBackend[] {
|
|
646
|
+
const healthy = this.getHealthy()
|
|
647
|
+
if (!this.rateLimiter) {
|
|
648
|
+
return healthy
|
|
649
|
+
}
|
|
650
|
+
return healthy.filter(backend => this.rateLimiter!.canAcquire(backend.name))
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Get ready backends for a specific chain
|
|
655
|
+
*
|
|
656
|
+
* @param chain - Chain type to filter by
|
|
657
|
+
* @returns Array of ready backends supporting the chain
|
|
658
|
+
*/
|
|
659
|
+
getReadyByChain(chain: ChainType): PrivacyBackend[] {
|
|
660
|
+
return this.getReady().filter(backend => backend.chains.includes(chain))
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Reset rate limit state for a backend
|
|
665
|
+
*
|
|
666
|
+
* Refills bucket to max tokens and clears stats.
|
|
667
|
+
*
|
|
668
|
+
* @param name - Backend name
|
|
669
|
+
*/
|
|
670
|
+
resetRateLimit(name: string): void {
|
|
671
|
+
this.rateLimiter?.reset(name)
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Dispose rate limiter resources
|
|
676
|
+
*
|
|
677
|
+
* Call when shutting down to clean up queue processing intervals.
|
|
678
|
+
*/
|
|
679
|
+
disposeRateLimiter(): void {
|
|
680
|
+
this.rateLimiter?.dispose()
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Global default registry instance
|
|
686
|
+
*
|
|
687
|
+
* Use this for simple applications, or create your own instance
|
|
688
|
+
* for more control.
|
|
689
|
+
*/
|
|
690
|
+
export const defaultRegistry = new PrivacyBackendRegistry()
|