@sip-protocol/sdk 0.7.3 → 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 +47556 -19603
- package/dist/browser.mjs +628 -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-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
- 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-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
- package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48396 -19623
- package/dist/index.mjs +537 -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 +252 -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 +47 -6
- 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 +186 -33
- package/src/chains/solana/providers/index.ts +31 -0
- package/src/chains/solana/providers/interface.ts +61 -18
- 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 +338 -67
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +83 -66
- 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 +57 -6
- 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 +23 -0
- package/src/compliance/range-sas.ts +398 -33
- 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 +686 -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 +254 -4
- package/src/privacy-backends/interface.ts +649 -6
- 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.ts +13 -17
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +414 -2
- package/src/privacy-backends/router.ts +283 -3
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +3 -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 +110 -29
- 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/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-2XIVXWHA.mjs +0 -1930
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-7RFRWDCW.mjs +0 -1504
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-F6F73W35.mjs +0 -16166
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-OFDBEIEK.mjs +0 -16166
- package/dist/chunk-SF7YSLF5.mjs +0 -1515
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/chunk-WWUSGOXE.mjs +0 -17129
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-B71aXVzk.d.ts +0 -13264
- 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-pOIIuwfV.d.mts +0 -13264
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-4O4K45VU.mjs +0 -46
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-NDABAZ6P.mjs +0 -56
- package/dist/solana-Q4NAVBTS.mjs +0 -46
- package/dist/solana-ZYO63LY5.mjs +0 -46
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShadowWire Privacy Backend
|
|
3
|
+
*
|
|
4
|
+
* Integrates ShadowWire by Radr Labs as a privacy backend for SIP Protocol.
|
|
5
|
+
* ShadowWire uses Pedersen Commitments + Bulletproofs for amount hiding.
|
|
6
|
+
*
|
|
7
|
+
* SIP adds viewing keys to ShadowWire for compliance support.
|
|
8
|
+
*
|
|
9
|
+
* @see https://radrlabs.io
|
|
10
|
+
* @see https://github.com/Radrdotfun/ShadowWire
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { ShadowWireBackend, PrivacyBackendRegistry } from '@sip-protocol/sdk'
|
|
15
|
+
*
|
|
16
|
+
* const backend = new ShadowWireBackend()
|
|
17
|
+
* const registry = new PrivacyBackendRegistry()
|
|
18
|
+
* registry.register(backend)
|
|
19
|
+
*
|
|
20
|
+
* // Execute private transfer
|
|
21
|
+
* const result = await backend.execute({
|
|
22
|
+
* chain: 'solana',
|
|
23
|
+
* sender: 'sender-pubkey',
|
|
24
|
+
* recipient: 'recipient-pubkey',
|
|
25
|
+
* mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
|
|
26
|
+
* amount: 1000000n, // 1 USDC
|
|
27
|
+
* decimals: 6,
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
ShadowWireClient,
|
|
34
|
+
type TransferType,
|
|
35
|
+
type TokenSymbol,
|
|
36
|
+
type WalletAdapter,
|
|
37
|
+
InsufficientBalanceError,
|
|
38
|
+
RecipientNotFoundError,
|
|
39
|
+
InvalidAmountError,
|
|
40
|
+
InvalidAddressError,
|
|
41
|
+
} from '@radr/shadowwire'
|
|
42
|
+
import type { ChainType, ViewingKey } from '@sip-protocol/types'
|
|
43
|
+
import type {
|
|
44
|
+
PrivacyBackend,
|
|
45
|
+
BackendType,
|
|
46
|
+
BackendCapabilities,
|
|
47
|
+
TransferParams,
|
|
48
|
+
TransactionResult,
|
|
49
|
+
AvailabilityResult,
|
|
50
|
+
BackendParams,
|
|
51
|
+
} from './interface'
|
|
52
|
+
import { isTransferParams } from './interface'
|
|
53
|
+
import { generateViewingKey, encryptForViewing } from '../privacy'
|
|
54
|
+
import type { HexString } from '@sip-protocol/types'
|
|
55
|
+
import { bytesToHex } from '@noble/hashes/utils'
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* ShadowWire supported token mint addresses
|
|
59
|
+
* Note: ShadowWire supports a specific set of tokens. Check SUPPORTED_TOKENS in @radr/shadowwire
|
|
60
|
+
*/
|
|
61
|
+
export const SHADOWWIRE_TOKEN_MINTS: Record<TokenSymbol, string> = {
|
|
62
|
+
SOL: 'So11111111111111111111111111111111111111112',
|
|
63
|
+
USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
64
|
+
RADR: 'RADRi35VqLmMu4t7Gax1KVszxnQnbtqEwJQJVfzpump',
|
|
65
|
+
ORE: 'oreoU2P8bN6jkk3jbaiVxYnG1dCXcYxwhycK7fw73F', // ORE mining token
|
|
66
|
+
BONK: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
|
|
67
|
+
JIM: 'JIMa1xG7h7h7h7h7h7h7h7h7h7h7h7h7h7h7h7h7', // Placeholder
|
|
68
|
+
GODL: 'GODL1111111111111111111111111111111111111', // Placeholder
|
|
69
|
+
HUSTLE: 'HUSTLEexampleaddress1111111111111111111', // Placeholder
|
|
70
|
+
ZEC: 'ZECexampleaddress1111111111111111111111111', // Placeholder
|
|
71
|
+
CRT: 'CRTexampleaddress11111111111111111111111111', // Placeholder
|
|
72
|
+
BLACKCOIN: 'BLACKexampleaddress111111111111111111111', // Placeholder
|
|
73
|
+
GIL: 'GILexampleaddress11111111111111111111111111', // Placeholder
|
|
74
|
+
ANON: 'ANONexampleaddress1111111111111111111111111', // Placeholder
|
|
75
|
+
WLFI: 'WLFIexampleaddress1111111111111111111111111', // Placeholder - World Liberty Financial
|
|
76
|
+
USD1: 'USD1exampleaddress1111111111111111111111111', // Placeholder - USD1 stablecoin
|
|
77
|
+
AOL: 'AOLexampleaddress11111111111111111111111111', // Placeholder
|
|
78
|
+
IQLABS: 'IQLABSexampleaddress111111111111111111111', // Placeholder - IQ Labs token
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Reverse lookup: mint address to symbol
|
|
83
|
+
*/
|
|
84
|
+
const MINT_TO_SYMBOL: Record<string, TokenSymbol> = Object.fromEntries(
|
|
85
|
+
Object.entries(SHADOWWIRE_TOKEN_MINTS).map(([symbol, mint]) => [mint, symbol as TokenSymbol])
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* ShadowWire backend configuration
|
|
90
|
+
*/
|
|
91
|
+
export interface ShadowWireBackendConfig {
|
|
92
|
+
/** API base URL (optional, uses default if not provided) */
|
|
93
|
+
apiBaseUrl?: string
|
|
94
|
+
/** Enable debug logging */
|
|
95
|
+
debug?: boolean
|
|
96
|
+
/** Default transfer type */
|
|
97
|
+
defaultTransferType?: TransferType
|
|
98
|
+
/** Wallet adapter for signing */
|
|
99
|
+
wallet?: WalletAdapter
|
|
100
|
+
/** Enable client-side proof generation (WASM) */
|
|
101
|
+
clientSideProofs?: boolean
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* ShadowWire backend capabilities
|
|
106
|
+
*/
|
|
107
|
+
const SHADOWWIRE_CAPABILITIES: BackendCapabilities = {
|
|
108
|
+
hiddenAmount: true,
|
|
109
|
+
hiddenSender: true,
|
|
110
|
+
hiddenRecipient: true, // Internal transfers only
|
|
111
|
+
hiddenCompute: false,
|
|
112
|
+
complianceSupport: true, // SIP adds viewing keys
|
|
113
|
+
anonymitySet: undefined, // Not pool-based
|
|
114
|
+
setupRequired: false,
|
|
115
|
+
latencyEstimate: 'medium', // ~500ms for proof generation
|
|
116
|
+
supportedTokens: 'spl',
|
|
117
|
+
minAmount: 1n, // Minimum 1 lamport
|
|
118
|
+
maxAmount: undefined,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* ShadowWire Privacy Backend
|
|
123
|
+
*
|
|
124
|
+
* Wraps the ShadowWire SDK to provide a unified PrivacyBackend interface.
|
|
125
|
+
* Adds SIP's viewing key support for compliance.
|
|
126
|
+
*/
|
|
127
|
+
export class ShadowWireBackend implements PrivacyBackend {
|
|
128
|
+
readonly name = 'shadowwire'
|
|
129
|
+
readonly type: BackendType = 'transaction'
|
|
130
|
+
readonly chains: ChainType[] = ['solana']
|
|
131
|
+
|
|
132
|
+
private client: ShadowWireClient
|
|
133
|
+
private config: ShadowWireBackendConfig
|
|
134
|
+
private wallet?: WalletAdapter
|
|
135
|
+
|
|
136
|
+
constructor(config: ShadowWireBackendConfig = {}) {
|
|
137
|
+
this.config = {
|
|
138
|
+
defaultTransferType: 'internal',
|
|
139
|
+
clientSideProofs: false,
|
|
140
|
+
...config,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.client = new ShadowWireClient({
|
|
144
|
+
debug: config.debug,
|
|
145
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
this.wallet = config.wallet
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Set wallet adapter for signing
|
|
153
|
+
*/
|
|
154
|
+
setWallet(wallet: WalletAdapter): void {
|
|
155
|
+
this.wallet = wallet
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Check if backend is available for given parameters
|
|
160
|
+
*/
|
|
161
|
+
async checkAvailability(params: BackendParams): Promise<AvailabilityResult> {
|
|
162
|
+
if (!isTransferParams(params)) {
|
|
163
|
+
return {
|
|
164
|
+
available: false,
|
|
165
|
+
reason: 'ShadowWire only supports transfer operations, not compute',
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Check chain support
|
|
170
|
+
if (params.chain !== 'solana') {
|
|
171
|
+
return {
|
|
172
|
+
available: false,
|
|
173
|
+
reason: `Chain '${params.chain}' not supported. ShadowWire only works on Solana`,
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Check token support
|
|
178
|
+
const tokenSymbol = this.getTokenSymbol(params.mint)
|
|
179
|
+
if (!tokenSymbol) {
|
|
180
|
+
return {
|
|
181
|
+
available: false,
|
|
182
|
+
reason: `Token mint '${params.mint}' not supported by ShadowWire`,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check amount validity
|
|
187
|
+
if (params.amount <= 0n) {
|
|
188
|
+
return {
|
|
189
|
+
available: false,
|
|
190
|
+
reason: 'Amount must be greater than 0',
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check balance (if wallet is connected)
|
|
195
|
+
if (this.wallet) {
|
|
196
|
+
try {
|
|
197
|
+
const balance = await this.client.getBalance(params.sender, tokenSymbol)
|
|
198
|
+
if (BigInt(balance.available) < params.amount) {
|
|
199
|
+
return {
|
|
200
|
+
available: false,
|
|
201
|
+
reason: `Insufficient ShadowWire balance. Have: ${balance.available}, Need: ${params.amount}`,
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} catch {
|
|
205
|
+
// Balance check failed, but might still be available
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
available: true,
|
|
211
|
+
estimatedCost: this.estimateTransferCost(params),
|
|
212
|
+
estimatedTime: 2000, // ~2s for proof generation + confirmation
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get backend capabilities
|
|
218
|
+
*/
|
|
219
|
+
getCapabilities(): BackendCapabilities {
|
|
220
|
+
return { ...SHADOWWIRE_CAPABILITIES }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Execute a privacy-preserving transfer via ShadowWire
|
|
225
|
+
*/
|
|
226
|
+
async execute(params: TransferParams): Promise<TransactionResult> {
|
|
227
|
+
// Validate parameters
|
|
228
|
+
const validation = await this.checkAvailability(params)
|
|
229
|
+
if (!validation.available) {
|
|
230
|
+
return {
|
|
231
|
+
success: false,
|
|
232
|
+
error: validation.reason,
|
|
233
|
+
backend: this.name,
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Get token symbol
|
|
238
|
+
const tokenSymbol = this.getTokenSymbol(params.mint)
|
|
239
|
+
if (!tokenSymbol) {
|
|
240
|
+
return {
|
|
241
|
+
success: false,
|
|
242
|
+
error: `Unsupported token: ${params.mint}`,
|
|
243
|
+
backend: this.name,
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Determine wallet
|
|
248
|
+
const wallet = this.wallet || (params.options?.wallet as WalletAdapter | undefined)
|
|
249
|
+
if (!wallet) {
|
|
250
|
+
return {
|
|
251
|
+
success: false,
|
|
252
|
+
error: 'Wallet adapter required for ShadowWire transfers. Set via setWallet() or options.wallet',
|
|
253
|
+
backend: this.name,
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
// Determine transfer type
|
|
259
|
+
const transferType: TransferType =
|
|
260
|
+
(params.options?.transferType as TransferType) ||
|
|
261
|
+
this.config.defaultTransferType ||
|
|
262
|
+
'internal'
|
|
263
|
+
|
|
264
|
+
// Convert amount to decimal (ShadowWire uses decimal amounts)
|
|
265
|
+
const decimalAmount = Number(params.amount) / Math.pow(10, params.decimals)
|
|
266
|
+
|
|
267
|
+
// Execute ShadowWire transfer
|
|
268
|
+
const response = await this.client.transfer({
|
|
269
|
+
sender: params.sender,
|
|
270
|
+
recipient: params.recipient,
|
|
271
|
+
amount: decimalAmount,
|
|
272
|
+
token: tokenSymbol,
|
|
273
|
+
type: transferType,
|
|
274
|
+
wallet,
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
// Generate SIP viewing key for compliance
|
|
278
|
+
let viewingKey: ViewingKey | undefined
|
|
279
|
+
let encryptedData: HexString | undefined
|
|
280
|
+
|
|
281
|
+
if (params.viewingKey || params.options?.generateViewingKey) {
|
|
282
|
+
viewingKey = params.viewingKey || generateViewingKey()
|
|
283
|
+
|
|
284
|
+
// Encrypt transaction details for viewing key holder
|
|
285
|
+
const txDetails = {
|
|
286
|
+
sender: params.sender,
|
|
287
|
+
recipient: params.recipient,
|
|
288
|
+
amount: params.amount.toString(),
|
|
289
|
+
token: tokenSymbol,
|
|
290
|
+
timestamp: Date.now(),
|
|
291
|
+
shadowwireTxId: response.tx_signature,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// encryptForViewing returns EncryptedTransaction object
|
|
295
|
+
const encrypted = encryptForViewing(txDetails, viewingKey)
|
|
296
|
+
// Convert to hex string for storage
|
|
297
|
+
const jsonBytes = new TextEncoder().encode(JSON.stringify(encrypted))
|
|
298
|
+
encryptedData = `0x${bytesToHex(jsonBytes)}` as HexString
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
success: true,
|
|
303
|
+
signature: response.tx_signature,
|
|
304
|
+
backend: this.name,
|
|
305
|
+
encryptedData,
|
|
306
|
+
metadata: {
|
|
307
|
+
transferType,
|
|
308
|
+
token: tokenSymbol,
|
|
309
|
+
viewingKeyGenerated: !!viewingKey,
|
|
310
|
+
},
|
|
311
|
+
}
|
|
312
|
+
} catch (error) {
|
|
313
|
+
return {
|
|
314
|
+
success: false,
|
|
315
|
+
error: this.formatError(error),
|
|
316
|
+
backend: this.name,
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Estimate cost for a transfer
|
|
323
|
+
*/
|
|
324
|
+
async estimateCost(params: BackendParams): Promise<bigint> {
|
|
325
|
+
if (!isTransferParams(params)) {
|
|
326
|
+
return 0n
|
|
327
|
+
}
|
|
328
|
+
return this.estimateTransferCost(params)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Get ShadowWire balance for a token
|
|
333
|
+
*/
|
|
334
|
+
async getBalance(walletAddress: string, token: TokenSymbol): Promise<bigint> {
|
|
335
|
+
const balance = await this.client.getBalance(walletAddress, token)
|
|
336
|
+
return BigInt(balance.available)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Deposit funds into ShadowWire pool
|
|
341
|
+
* Returns an unsigned transaction that must be signed and sent by the caller
|
|
342
|
+
*/
|
|
343
|
+
async deposit(
|
|
344
|
+
walletAddress: string,
|
|
345
|
+
amount: number,
|
|
346
|
+
tokenMint?: string
|
|
347
|
+
): Promise<{ unsignedTx: string; poolAddress: string }> {
|
|
348
|
+
const response = await this.client.deposit({
|
|
349
|
+
wallet: walletAddress,
|
|
350
|
+
amount,
|
|
351
|
+
token_mint: tokenMint,
|
|
352
|
+
})
|
|
353
|
+
return {
|
|
354
|
+
unsignedTx: response.unsigned_tx_base64,
|
|
355
|
+
poolAddress: response.pool_address,
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Withdraw funds from ShadowWire pool
|
|
361
|
+
* Returns an unsigned transaction that must be signed and sent by the caller
|
|
362
|
+
*/
|
|
363
|
+
async withdraw(
|
|
364
|
+
walletAddress: string,
|
|
365
|
+
amount: number,
|
|
366
|
+
tokenMint?: string
|
|
367
|
+
): Promise<{ unsignedTx: string; amountWithdrawn: number; fee: number }> {
|
|
368
|
+
const response = await this.client.withdraw({
|
|
369
|
+
wallet: walletAddress,
|
|
370
|
+
amount,
|
|
371
|
+
token_mint: tokenMint,
|
|
372
|
+
})
|
|
373
|
+
return {
|
|
374
|
+
unsignedTx: response.unsigned_tx_base64,
|
|
375
|
+
amountWithdrawn: response.amount_withdrawn,
|
|
376
|
+
fee: response.fee,
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get underlying ShadowWire client
|
|
382
|
+
*/
|
|
383
|
+
getClient(): ShadowWireClient {
|
|
384
|
+
return this.client
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ─── Private Helpers ───────────────────────────────────────────────────────
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Get token symbol from mint address
|
|
391
|
+
*/
|
|
392
|
+
private getTokenSymbol(mint: string | null): TokenSymbol | undefined {
|
|
393
|
+
if (!mint) {
|
|
394
|
+
return 'SOL'
|
|
395
|
+
}
|
|
396
|
+
return MINT_TO_SYMBOL[mint]
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Estimate transfer cost in lamports
|
|
401
|
+
*/
|
|
402
|
+
private estimateTransferCost(params: TransferParams): bigint {
|
|
403
|
+
// Base transaction fee
|
|
404
|
+
let cost = 5000n // ~0.000005 SOL
|
|
405
|
+
|
|
406
|
+
// Add proof generation cost estimate
|
|
407
|
+
const transferType =
|
|
408
|
+
(params.options?.transferType as TransferType) ||
|
|
409
|
+
this.config.defaultTransferType ||
|
|
410
|
+
'internal'
|
|
411
|
+
|
|
412
|
+
if (transferType === 'internal') {
|
|
413
|
+
cost += 10000n // Additional cost for ZK proof verification
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return cost
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Format error for user-friendly message
|
|
421
|
+
*/
|
|
422
|
+
private formatError(error: unknown): string {
|
|
423
|
+
if (error instanceof InsufficientBalanceError) {
|
|
424
|
+
return 'Insufficient balance in ShadowWire pool. Deposit funds first.'
|
|
425
|
+
}
|
|
426
|
+
if (error instanceof RecipientNotFoundError) {
|
|
427
|
+
return 'Recipient must be a ShadowWire user for internal transfers. Use external transfer type for non-users.'
|
|
428
|
+
}
|
|
429
|
+
if (error instanceof InvalidAmountError) {
|
|
430
|
+
return 'Invalid transfer amount'
|
|
431
|
+
}
|
|
432
|
+
if (error instanceof InvalidAddressError) {
|
|
433
|
+
return 'Invalid Solana address'
|
|
434
|
+
}
|
|
435
|
+
if (error instanceof Error) {
|
|
436
|
+
return error.message
|
|
437
|
+
}
|
|
438
|
+
return 'Unknown ShadowWire error'
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Create a ShadowWire backend with default configuration
|
|
444
|
+
*/
|
|
445
|
+
export function createShadowWireBackend(
|
|
446
|
+
config?: ShadowWireBackendConfig
|
|
447
|
+
): ShadowWireBackend {
|
|
448
|
+
return new ShadowWireBackend(config)
|
|
449
|
+
}
|
|
@@ -38,7 +38,9 @@ import type {
|
|
|
38
38
|
TransferParams,
|
|
39
39
|
TransactionResult,
|
|
40
40
|
AvailabilityResult,
|
|
41
|
+
PrivacyBackendVersion,
|
|
41
42
|
} from './interface'
|
|
43
|
+
import { CURRENT_BACKEND_VERSION } from './interface'
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
46
|
* Supported chains for SIP Native backend
|
|
@@ -93,6 +95,7 @@ export interface SIPNativeBackendConfig {
|
|
|
93
95
|
* with viewing key support for regulatory compliance.
|
|
94
96
|
*/
|
|
95
97
|
export class SIPNativeBackend implements PrivacyBackend {
|
|
98
|
+
readonly version: PrivacyBackendVersion = CURRENT_BACKEND_VERSION
|
|
96
99
|
readonly name = 'sip-native'
|
|
97
100
|
readonly type: BackendType = 'transaction'
|
|
98
101
|
readonly chains: ChainType[]
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy-Aware Logger
|
|
3
|
+
*
|
|
4
|
+
* Provides logging utilities that automatically redact sensitive information
|
|
5
|
+
* like wallet addresses and transaction amounts to prevent privacy leaks
|
|
6
|
+
* through log aggregators or error reporting tools.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'
|
|
10
|
+
|
|
11
|
+
export interface PrivacyLoggerConfig {
|
|
12
|
+
prefix?: string
|
|
13
|
+
level?: LogLevel
|
|
14
|
+
productionMode?: boolean
|
|
15
|
+
output?: (level: LogLevel, message: string) => void
|
|
16
|
+
silent?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SensitiveData {
|
|
20
|
+
address?: string
|
|
21
|
+
from?: string
|
|
22
|
+
to?: string
|
|
23
|
+
owner?: string
|
|
24
|
+
amount?: bigint | number | string
|
|
25
|
+
signature?: string
|
|
26
|
+
txHash?: string
|
|
27
|
+
[key: string]: unknown
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
|
|
31
|
+
debug: 0,
|
|
32
|
+
info: 1,
|
|
33
|
+
warn: 2,
|
|
34
|
+
error: 3,
|
|
35
|
+
silent: 4,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ADDRESS_FIELDS = new Set([
|
|
39
|
+
'address', 'from', 'to', 'owner', 'sender', 'recipient', 'wallet', 'publicKey', 'pubkey',
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
const TX_FIELDS = new Set([
|
|
43
|
+
'signature', 'txHash', 'txSignature', 'transactionHash', 'computationId',
|
|
44
|
+
])
|
|
45
|
+
|
|
46
|
+
export function redactAddress(address: string, chars: number = 4): string {
|
|
47
|
+
if (!address || typeof address !== 'string') return '[invalid]'
|
|
48
|
+
if (address.length <= chars * 2 + 3) return address
|
|
49
|
+
return `${address.slice(0, chars)}...${address.slice(-chars)}`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function redactSignature(signature: string, chars: number = 6): string {
|
|
53
|
+
if (!signature || typeof signature !== 'string') return '[invalid]'
|
|
54
|
+
if (signature.length <= chars * 2 + 3) return signature
|
|
55
|
+
return `${signature.slice(0, chars)}...${signature.slice(-chars)}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function maskAmount(
|
|
59
|
+
amount: bigint | number | string,
|
|
60
|
+
decimals: number = 9,
|
|
61
|
+
symbol: string = ''
|
|
62
|
+
): string {
|
|
63
|
+
let value: number
|
|
64
|
+
if (typeof amount === 'bigint') {
|
|
65
|
+
value = Number(amount) / 10 ** decimals
|
|
66
|
+
} else if (typeof amount === 'string') {
|
|
67
|
+
value = parseFloat(amount)
|
|
68
|
+
if (isNaN(value)) return '[hidden]'
|
|
69
|
+
} else {
|
|
70
|
+
value = amount / 10 ** decimals
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let range: string
|
|
74
|
+
if (value <= 0) range = '0'
|
|
75
|
+
else if (value < 0.01) range = '<0.01'
|
|
76
|
+
else if (value < 0.1) range = '0.01-0.1'
|
|
77
|
+
else if (value < 1) range = '0.1-1'
|
|
78
|
+
else if (value < 10) range = '1-10'
|
|
79
|
+
else if (value < 100) range = '10-100'
|
|
80
|
+
else if (value < 1000) range = '100-1K'
|
|
81
|
+
else if (value < 10000) range = '1K-10K'
|
|
82
|
+
else if (value < 100000) range = '10K-100K'
|
|
83
|
+
else range = '>100K'
|
|
84
|
+
|
|
85
|
+
return symbol ? `${range} ${symbol}` : range
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function redactSensitiveData(
|
|
89
|
+
data: SensitiveData,
|
|
90
|
+
productionMode: boolean = false
|
|
91
|
+
): Record<string, string | undefined> {
|
|
92
|
+
const result: Record<string, string | undefined> = {}
|
|
93
|
+
for (const [key, value] of Object.entries(data)) {
|
|
94
|
+
if (value === undefined || value === null) {
|
|
95
|
+
result[key] = undefined
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
98
|
+
if (ADDRESS_FIELDS.has(key) && typeof value === 'string') {
|
|
99
|
+
result[key] = redactAddress(value)
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
if (TX_FIELDS.has(key) && typeof value === 'string') {
|
|
103
|
+
result[key] = redactSignature(value)
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
if (key === 'amount' || key.toLowerCase().includes('amount')) {
|
|
107
|
+
if (typeof value === 'bigint' || typeof value === 'number' || typeof value === 'string') {
|
|
108
|
+
result[key] = productionMode ? '[hidden]' : maskAmount(value)
|
|
109
|
+
}
|
|
110
|
+
continue
|
|
111
|
+
}
|
|
112
|
+
if (typeof value === 'string') result[key] = value
|
|
113
|
+
else if (typeof value === 'number' || typeof value === 'bigint') result[key] = value.toString()
|
|
114
|
+
else if (typeof value === 'boolean') result[key] = value.toString()
|
|
115
|
+
else result[key] = '[object]'
|
|
116
|
+
}
|
|
117
|
+
return result
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export class PrivacyLogger {
|
|
121
|
+
private config: Required<PrivacyLoggerConfig>
|
|
122
|
+
|
|
123
|
+
constructor(config: PrivacyLoggerConfig = {}) {
|
|
124
|
+
this.config = {
|
|
125
|
+
prefix: config.prefix ?? '',
|
|
126
|
+
level: config.level ?? 'info',
|
|
127
|
+
productionMode: config.productionMode ?? false,
|
|
128
|
+
silent: config.silent ?? false,
|
|
129
|
+
output: config.output ?? this.defaultOutput.bind(this),
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private defaultOutput(level: LogLevel, message: string): void {
|
|
134
|
+
switch (level) {
|
|
135
|
+
case 'debug': console.debug(message); break
|
|
136
|
+
case 'info': console.info(message); break
|
|
137
|
+
case 'warn': console.warn(message); break
|
|
138
|
+
case 'error': console.error(message); break
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private shouldLog(level: LogLevel): boolean {
|
|
143
|
+
if (this.config.silent) return false
|
|
144
|
+
return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.config.level]
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private formatMessage(message: string, data?: SensitiveData): string {
|
|
148
|
+
const prefix = this.config.prefix ? `${this.config.prefix} ` : ''
|
|
149
|
+
if (!data || Object.keys(data).length === 0) return `${prefix}${message}`
|
|
150
|
+
const redacted = redactSensitiveData(data, this.config.productionMode)
|
|
151
|
+
const dataStr = Object.entries(redacted)
|
|
152
|
+
.filter(([, v]) => v !== undefined)
|
|
153
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
154
|
+
.join(' ')
|
|
155
|
+
return `${prefix}${message} ${dataStr}`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
debug(message: string, data?: SensitiveData): void {
|
|
159
|
+
if (this.shouldLog('debug')) this.config.output('debug', this.formatMessage(message, data))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
info(message: string, data?: SensitiveData): void {
|
|
163
|
+
if (this.shouldLog('info')) this.config.output('info', this.formatMessage(message, data))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
warn(message: string, data?: SensitiveData): void {
|
|
167
|
+
if (this.shouldLog('warn')) this.config.output('warn', this.formatMessage(message, data))
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
error(message: string, data?: SensitiveData): void {
|
|
171
|
+
if (this.shouldLog('error')) this.config.output('error', this.formatMessage(message, data))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
configure(config: Partial<PrivacyLoggerConfig>): void {
|
|
175
|
+
this.config = { ...this.config, ...config }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
child(prefix: string): PrivacyLogger {
|
|
179
|
+
const childPrefix = this.config.prefix ? `${this.config.prefix}${prefix}` : prefix
|
|
180
|
+
return new PrivacyLogger({ ...this.config, prefix: childPrefix })
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const privacyLogger = new PrivacyLogger({ prefix: '[SIP]', level: 'warn' })
|
|
185
|
+
|
|
186
|
+
export function createPrivacyLogger(
|
|
187
|
+
moduleName: string,
|
|
188
|
+
config: Partial<PrivacyLoggerConfig> = {}
|
|
189
|
+
): PrivacyLogger {
|
|
190
|
+
return new PrivacyLogger({ prefix: `[${moduleName}]`, level: 'warn', ...config })
|
|
191
|
+
}
|