@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,921 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fireblocks Viewing Key API Integration
|
|
3
|
+
*
|
|
4
|
+
* Integrates viewing key API with Fireblocks, the leading institutional custody platform.
|
|
5
|
+
* Enables compliance officers using Fireblocks to access SIP Protocol transaction history
|
|
6
|
+
* with cryptographic privacy guarantees.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { FireblocksViewingKeyClient, createFireblocksClient } from '@sip-protocol/sdk'
|
|
11
|
+
*
|
|
12
|
+
* const client = createFireblocksClient({
|
|
13
|
+
* apiKey: process.env.FIREBLOCKS_API_KEY!,
|
|
14
|
+
* secretKey: process.env.FIREBLOCKS_SECRET_KEY!,
|
|
15
|
+
* vaultAccountId: 'vault-123',
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* // Register viewing key for compliance
|
|
19
|
+
* const registration = await client.registerViewingKey({
|
|
20
|
+
* viewingKey: orgViewingKey,
|
|
21
|
+
* auditorName: 'Compliance Team',
|
|
22
|
+
* scope: { transactionTypes: ['transfer', 'swap'] },
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* // Export transaction history for audit
|
|
26
|
+
* const history = await client.exportTransactionHistory({
|
|
27
|
+
* viewingKey: orgViewingKey,
|
|
28
|
+
* startDate: new Date('2025-01-01'),
|
|
29
|
+
* endDate: new Date('2025-12-31'),
|
|
30
|
+
* format: 'csv',
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @see https://docs.fireblocks.com/api/
|
|
35
|
+
* @see https://docs.fireblocks.com/api/#signing-a-request
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { sha256 } from '@noble/hashes/sha256'
|
|
39
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
|
|
40
|
+
import type { ViewingKey, EncryptedTransaction, Hash } from '@sip-protocol/types'
|
|
41
|
+
import { decryptWithViewing, type TransactionData } from '../privacy'
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fireblocks API configuration
|
|
45
|
+
*/
|
|
46
|
+
export interface FireblocksConfig {
|
|
47
|
+
/** Fireblocks API key */
|
|
48
|
+
apiKey: string
|
|
49
|
+
/** Fireblocks secret key (RSA private key for signing) */
|
|
50
|
+
secretKey: string
|
|
51
|
+
/** Vault account ID for operations */
|
|
52
|
+
vaultAccountId: string
|
|
53
|
+
/** Base URL (defaults to production) */
|
|
54
|
+
baseUrl?: string
|
|
55
|
+
/** Request timeout in ms (default: 30000) */
|
|
56
|
+
timeout?: number
|
|
57
|
+
/** Enable sandbox mode for testing */
|
|
58
|
+
sandbox?: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Viewing key registration parameters
|
|
63
|
+
*/
|
|
64
|
+
export interface RegisterViewingKeyParams {
|
|
65
|
+
/** The viewing key to register */
|
|
66
|
+
viewingKey: ViewingKey
|
|
67
|
+
/** Name of the auditor/compliance team */
|
|
68
|
+
auditorName: string
|
|
69
|
+
/** Scope of access */
|
|
70
|
+
scope: ViewingKeyScope
|
|
71
|
+
/** Expiration date (optional) */
|
|
72
|
+
expiresAt?: Date
|
|
73
|
+
/** Metadata for compliance records */
|
|
74
|
+
metadata?: Record<string, string>
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Scope of viewing key access
|
|
79
|
+
*/
|
|
80
|
+
export interface ViewingKeyScope {
|
|
81
|
+
/** Transaction types to include */
|
|
82
|
+
transactionTypes?: TransactionType[]
|
|
83
|
+
/** Chain IDs to include */
|
|
84
|
+
chains?: string[]
|
|
85
|
+
/** Token/asset addresses to include */
|
|
86
|
+
assets?: string[]
|
|
87
|
+
/** Minimum amount threshold */
|
|
88
|
+
minAmount?: bigint
|
|
89
|
+
/** Maximum amount threshold */
|
|
90
|
+
maxAmount?: bigint
|
|
91
|
+
/** Start date for transaction range */
|
|
92
|
+
startDate?: Date
|
|
93
|
+
/** End date for transaction range */
|
|
94
|
+
endDate?: Date
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Transaction types for scoping
|
|
99
|
+
*/
|
|
100
|
+
export type TransactionType =
|
|
101
|
+
| 'transfer'
|
|
102
|
+
| 'swap'
|
|
103
|
+
| 'deposit'
|
|
104
|
+
| 'withdrawal'
|
|
105
|
+
| 'stake'
|
|
106
|
+
| 'unstake'
|
|
107
|
+
| 'bridge'
|
|
108
|
+
| 'mint'
|
|
109
|
+
| 'burn'
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Viewing key registration result
|
|
113
|
+
*/
|
|
114
|
+
export interface ViewingKeyRegistration {
|
|
115
|
+
/** Registration ID */
|
|
116
|
+
id: string
|
|
117
|
+
/** Viewing key hash (for identification) */
|
|
118
|
+
viewingKeyHash: Hash
|
|
119
|
+
/** Auditor name */
|
|
120
|
+
auditorName: string
|
|
121
|
+
/** Access scope */
|
|
122
|
+
scope: ViewingKeyScope
|
|
123
|
+
/** When registered */
|
|
124
|
+
registeredAt: Date
|
|
125
|
+
/** When expires */
|
|
126
|
+
expiresAt?: Date
|
|
127
|
+
/** Registration status */
|
|
128
|
+
status: RegistrationStatus
|
|
129
|
+
/** Fireblocks vault account */
|
|
130
|
+
vaultAccountId: string
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Registration status
|
|
135
|
+
*/
|
|
136
|
+
export type RegistrationStatus = 'active' | 'expired' | 'revoked' | 'pending'
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Transaction history export parameters
|
|
140
|
+
*/
|
|
141
|
+
export interface ExportTransactionHistoryParams {
|
|
142
|
+
/** Viewing key for decryption */
|
|
143
|
+
viewingKey: ViewingKey
|
|
144
|
+
/** Start date */
|
|
145
|
+
startDate: Date
|
|
146
|
+
/** End date */
|
|
147
|
+
endDate: Date
|
|
148
|
+
/** Export format */
|
|
149
|
+
format: ExportFormat
|
|
150
|
+
/** Include raw encrypted data */
|
|
151
|
+
includeRaw?: boolean
|
|
152
|
+
/** Filter by transaction types */
|
|
153
|
+
transactionTypes?: TransactionType[]
|
|
154
|
+
/** Filter by chains */
|
|
155
|
+
chains?: string[]
|
|
156
|
+
/** Filter by assets */
|
|
157
|
+
assets?: string[]
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Export format options
|
|
162
|
+
*/
|
|
163
|
+
export type ExportFormat = 'json' | 'csv' | 'pdf'
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Transaction history export result
|
|
167
|
+
*/
|
|
168
|
+
export interface TransactionHistoryExport {
|
|
169
|
+
/** Export ID */
|
|
170
|
+
id: string
|
|
171
|
+
/** When generated */
|
|
172
|
+
generatedAt: Date
|
|
173
|
+
/** Export format */
|
|
174
|
+
format: ExportFormat
|
|
175
|
+
/** Number of transactions */
|
|
176
|
+
transactionCount: number
|
|
177
|
+
/** Date range */
|
|
178
|
+
dateRange: { start: Date; end: Date }
|
|
179
|
+
/** Export data (base64 for PDF, string for CSV, object for JSON) */
|
|
180
|
+
data: string | DecryptedTransaction[]
|
|
181
|
+
/** Checksum for verification */
|
|
182
|
+
checksum: Hash
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Decrypted transaction for export
|
|
187
|
+
*/
|
|
188
|
+
export interface DecryptedTransaction {
|
|
189
|
+
/** Transaction ID */
|
|
190
|
+
id: string
|
|
191
|
+
/** Transaction type */
|
|
192
|
+
type: TransactionType
|
|
193
|
+
/** Chain ID */
|
|
194
|
+
chain: string
|
|
195
|
+
/** Sender address (decrypted) */
|
|
196
|
+
sender: string
|
|
197
|
+
/** Recipient address (decrypted) */
|
|
198
|
+
recipient: string
|
|
199
|
+
/** Amount (decrypted) */
|
|
200
|
+
amount: string
|
|
201
|
+
/** Asset/token */
|
|
202
|
+
asset: string
|
|
203
|
+
/** Timestamp */
|
|
204
|
+
timestamp: Date
|
|
205
|
+
/** Fireblocks transaction ID (if available) */
|
|
206
|
+
fireblocksId?: string
|
|
207
|
+
/** Risk score (0-100) */
|
|
208
|
+
riskScore?: number
|
|
209
|
+
/** Tags/labels */
|
|
210
|
+
tags?: string[]
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Compliance report parameters
|
|
215
|
+
*/
|
|
216
|
+
export interface GenerateComplianceReportParams {
|
|
217
|
+
/** Viewing key for decryption */
|
|
218
|
+
viewingKey: ViewingKey
|
|
219
|
+
/** Report type */
|
|
220
|
+
reportType: ComplianceReportType
|
|
221
|
+
/** Reporting period start */
|
|
222
|
+
periodStart: Date
|
|
223
|
+
/** Reporting period end */
|
|
224
|
+
periodEnd: Date
|
|
225
|
+
/** Include transaction details */
|
|
226
|
+
includeDetails?: boolean
|
|
227
|
+
/** Include risk analysis */
|
|
228
|
+
includeRiskAnalysis?: boolean
|
|
229
|
+
/** Output format */
|
|
230
|
+
format: ExportFormat
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Compliance report types
|
|
235
|
+
*/
|
|
236
|
+
export type ComplianceReportType =
|
|
237
|
+
| 'transaction_summary'
|
|
238
|
+
| 'audit_trail'
|
|
239
|
+
| 'risk_assessment'
|
|
240
|
+
| 'regulatory_filing'
|
|
241
|
+
| 'tax_report'
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Compliance report result
|
|
245
|
+
*/
|
|
246
|
+
export interface ComplianceReport {
|
|
247
|
+
/** Report ID */
|
|
248
|
+
id: string
|
|
249
|
+
/** Report type */
|
|
250
|
+
type: ComplianceReportType
|
|
251
|
+
/** When generated */
|
|
252
|
+
generatedAt: Date
|
|
253
|
+
/** Reporting period */
|
|
254
|
+
period: { start: Date; end: Date }
|
|
255
|
+
/** Summary statistics */
|
|
256
|
+
summary: {
|
|
257
|
+
totalTransactions: number
|
|
258
|
+
totalVolume: string
|
|
259
|
+
uniqueCounterparties: number
|
|
260
|
+
averageRiskScore: number
|
|
261
|
+
flaggedTransactions: number
|
|
262
|
+
}
|
|
263
|
+
/** Report data */
|
|
264
|
+
data: string | Record<string, unknown>
|
|
265
|
+
/** Format */
|
|
266
|
+
format: ExportFormat
|
|
267
|
+
/** Checksum */
|
|
268
|
+
checksum: Hash
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Fireblocks API error
|
|
273
|
+
*/
|
|
274
|
+
export class FireblocksError extends Error {
|
|
275
|
+
code: FireblocksErrorCode
|
|
276
|
+
statusCode?: number
|
|
277
|
+
details?: unknown
|
|
278
|
+
|
|
279
|
+
constructor(message: string, code: FireblocksErrorCode, statusCode?: number, details?: unknown) {
|
|
280
|
+
super(message)
|
|
281
|
+
this.name = 'FireblocksError'
|
|
282
|
+
this.code = code
|
|
283
|
+
this.statusCode = statusCode
|
|
284
|
+
this.details = details
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Error codes for Fireblocks integration
|
|
290
|
+
*/
|
|
291
|
+
export enum FireblocksErrorCode {
|
|
292
|
+
AUTHENTICATION_FAILED = 'AUTHENTICATION_FAILED',
|
|
293
|
+
INVALID_VIEWING_KEY = 'INVALID_VIEWING_KEY',
|
|
294
|
+
REGISTRATION_FAILED = 'REGISTRATION_FAILED',
|
|
295
|
+
EXPORT_FAILED = 'EXPORT_FAILED',
|
|
296
|
+
DECRYPTION_FAILED = 'DECRYPTION_FAILED',
|
|
297
|
+
API_ERROR = 'API_ERROR',
|
|
298
|
+
RATE_LIMITED = 'RATE_LIMITED',
|
|
299
|
+
TIMEOUT = 'TIMEOUT',
|
|
300
|
+
INVALID_SCOPE = 'INVALID_SCOPE',
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Fireblocks Viewing Key Client
|
|
305
|
+
*
|
|
306
|
+
* Integrates SIP Protocol viewing keys with Fireblocks institutional custody.
|
|
307
|
+
*/
|
|
308
|
+
export class FireblocksViewingKeyClient {
|
|
309
|
+
private readonly apiKey: string
|
|
310
|
+
private readonly secretKey: string
|
|
311
|
+
private readonly vaultAccountId: string
|
|
312
|
+
|
|
313
|
+
/** In-memory registration storage (production would use secure backend) */
|
|
314
|
+
private registrations: Map<string, ViewingKeyRegistration> = new Map()
|
|
315
|
+
private exports: Map<string, TransactionHistoryExport> = new Map()
|
|
316
|
+
private reports: Map<string, ComplianceReport> = new Map()
|
|
317
|
+
|
|
318
|
+
constructor(config: FireblocksConfig) {
|
|
319
|
+
this.apiKey = config.apiKey
|
|
320
|
+
this.secretKey = config.secretKey
|
|
321
|
+
this.vaultAccountId = config.vaultAccountId
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Register a viewing key for compliance access
|
|
326
|
+
*
|
|
327
|
+
* @param params - Registration parameters
|
|
328
|
+
* @returns Registration result
|
|
329
|
+
*/
|
|
330
|
+
async registerViewingKey(params: RegisterViewingKeyParams): Promise<ViewingKeyRegistration> {
|
|
331
|
+
// Validate viewing key
|
|
332
|
+
if (!this.isValidViewingKey(params.viewingKey)) {
|
|
333
|
+
throw new FireblocksError(
|
|
334
|
+
'Invalid viewing key format',
|
|
335
|
+
FireblocksErrorCode.INVALID_VIEWING_KEY
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Validate scope
|
|
340
|
+
if (!this.isValidScope(params.scope)) {
|
|
341
|
+
throw new FireblocksError(
|
|
342
|
+
'Invalid scope configuration',
|
|
343
|
+
FireblocksErrorCode.INVALID_SCOPE
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Compute viewing key hash for identification
|
|
348
|
+
const viewingKeyHash = this.computeViewingKeyHash(params.viewingKey)
|
|
349
|
+
|
|
350
|
+
// Check for existing registration
|
|
351
|
+
const existing = Array.from(this.registrations.values())
|
|
352
|
+
.find(r => r.viewingKeyHash === viewingKeyHash && r.status === 'active')
|
|
353
|
+
|
|
354
|
+
if (existing) {
|
|
355
|
+
throw new FireblocksError(
|
|
356
|
+
'Viewing key already registered',
|
|
357
|
+
FireblocksErrorCode.REGISTRATION_FAILED
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Create registration
|
|
362
|
+
const registration: ViewingKeyRegistration = {
|
|
363
|
+
id: this.generateId('reg'),
|
|
364
|
+
viewingKeyHash,
|
|
365
|
+
auditorName: params.auditorName,
|
|
366
|
+
scope: params.scope,
|
|
367
|
+
registeredAt: new Date(),
|
|
368
|
+
expiresAt: params.expiresAt,
|
|
369
|
+
status: 'active',
|
|
370
|
+
vaultAccountId: this.vaultAccountId,
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Store registration
|
|
374
|
+
this.registrations.set(registration.id, registration)
|
|
375
|
+
|
|
376
|
+
// In production, this would sync to Fireblocks via API
|
|
377
|
+
// await this.syncRegistrationToFireblocks(registration)
|
|
378
|
+
|
|
379
|
+
return registration
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get a viewing key registration
|
|
384
|
+
*
|
|
385
|
+
* @param registrationId - Registration ID
|
|
386
|
+
* @returns Registration or null
|
|
387
|
+
*/
|
|
388
|
+
getRegistration(registrationId: string): ViewingKeyRegistration | null {
|
|
389
|
+
return this.registrations.get(registrationId) ?? null
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* List all registrations for the vault
|
|
394
|
+
*
|
|
395
|
+
* @returns All registrations
|
|
396
|
+
*/
|
|
397
|
+
listRegistrations(): ViewingKeyRegistration[] {
|
|
398
|
+
return Array.from(this.registrations.values())
|
|
399
|
+
.filter(r => r.vaultAccountId === this.vaultAccountId)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Revoke a viewing key registration
|
|
404
|
+
*
|
|
405
|
+
* @param registrationId - Registration to revoke
|
|
406
|
+
* @param reason - Reason for revocation
|
|
407
|
+
*/
|
|
408
|
+
async revokeRegistration(registrationId: string, reason: string): Promise<void> {
|
|
409
|
+
const registration = this.registrations.get(registrationId)
|
|
410
|
+
|
|
411
|
+
if (!registration) {
|
|
412
|
+
throw new FireblocksError(
|
|
413
|
+
'Registration not found',
|
|
414
|
+
FireblocksErrorCode.REGISTRATION_FAILED
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
registration.status = 'revoked'
|
|
419
|
+
this.registrations.set(registrationId, registration)
|
|
420
|
+
|
|
421
|
+
// In production, sync revocation to Fireblocks
|
|
422
|
+
// await this.syncRevocationToFireblocks(registrationId, reason)
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Export transaction history using viewing key
|
|
427
|
+
*
|
|
428
|
+
* @param params - Export parameters
|
|
429
|
+
* @param encryptedTransactions - Encrypted transactions to export
|
|
430
|
+
* @returns Export result
|
|
431
|
+
*/
|
|
432
|
+
async exportTransactionHistory(
|
|
433
|
+
params: ExportTransactionHistoryParams,
|
|
434
|
+
encryptedTransactions: EncryptedTransaction[]
|
|
435
|
+
): Promise<TransactionHistoryExport> {
|
|
436
|
+
// Validate viewing key
|
|
437
|
+
if (!this.isValidViewingKey(params.viewingKey)) {
|
|
438
|
+
throw new FireblocksError(
|
|
439
|
+
'Invalid viewing key',
|
|
440
|
+
FireblocksErrorCode.INVALID_VIEWING_KEY
|
|
441
|
+
)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Verify viewing key is registered
|
|
445
|
+
const viewingKeyHash = this.computeViewingKeyHash(params.viewingKey)
|
|
446
|
+
const registration = Array.from(this.registrations.values())
|
|
447
|
+
.find(r => r.viewingKeyHash === viewingKeyHash && r.status === 'active')
|
|
448
|
+
|
|
449
|
+
if (!registration) {
|
|
450
|
+
throw new FireblocksError(
|
|
451
|
+
'Viewing key not registered or inactive',
|
|
452
|
+
FireblocksErrorCode.INVALID_VIEWING_KEY
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Decrypt transactions
|
|
457
|
+
const decryptedTransactions: DecryptedTransaction[] = []
|
|
458
|
+
|
|
459
|
+
for (const encrypted of encryptedTransactions) {
|
|
460
|
+
try {
|
|
461
|
+
// Verify viewing key hash matches
|
|
462
|
+
if (encrypted.viewingKeyHash !== viewingKeyHash) {
|
|
463
|
+
continue // Skip transactions encrypted with different key
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const decrypted = decryptWithViewing(encrypted, params.viewingKey)
|
|
467
|
+
|
|
468
|
+
// Apply filters
|
|
469
|
+
if (params.startDate && new Date(decrypted.timestamp) < params.startDate) continue
|
|
470
|
+
if (params.endDate && new Date(decrypted.timestamp) > params.endDate) continue
|
|
471
|
+
|
|
472
|
+
decryptedTransactions.push(this.mapToDecryptedTransaction(decrypted, encrypted))
|
|
473
|
+
} catch {
|
|
474
|
+
// Skip transactions that can't be decrypted
|
|
475
|
+
continue
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Format export
|
|
480
|
+
let data: string | DecryptedTransaction[]
|
|
481
|
+
|
|
482
|
+
switch (params.format) {
|
|
483
|
+
case 'json':
|
|
484
|
+
data = decryptedTransactions
|
|
485
|
+
break
|
|
486
|
+
case 'csv':
|
|
487
|
+
data = this.formatAsCsv(decryptedTransactions)
|
|
488
|
+
break
|
|
489
|
+
case 'pdf':
|
|
490
|
+
data = this.formatAsPdfBase64(decryptedTransactions)
|
|
491
|
+
break
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Create export record
|
|
495
|
+
const exportResult: TransactionHistoryExport = {
|
|
496
|
+
id: this.generateId('exp'),
|
|
497
|
+
generatedAt: new Date(),
|
|
498
|
+
format: params.format,
|
|
499
|
+
transactionCount: decryptedTransactions.length,
|
|
500
|
+
dateRange: { start: params.startDate, end: params.endDate },
|
|
501
|
+
data,
|
|
502
|
+
checksum: this.computeChecksum(data),
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
this.exports.set(exportResult.id, exportResult)
|
|
506
|
+
|
|
507
|
+
return exportResult
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Generate a compliance report
|
|
512
|
+
*
|
|
513
|
+
* @param params - Report parameters
|
|
514
|
+
* @param encryptedTransactions - Encrypted transactions
|
|
515
|
+
* @returns Compliance report
|
|
516
|
+
*/
|
|
517
|
+
async generateComplianceReport(
|
|
518
|
+
params: GenerateComplianceReportParams,
|
|
519
|
+
encryptedTransactions: EncryptedTransaction[]
|
|
520
|
+
): Promise<ComplianceReport> {
|
|
521
|
+
// First, export transaction history
|
|
522
|
+
const historyExport = await this.exportTransactionHistory(
|
|
523
|
+
{
|
|
524
|
+
viewingKey: params.viewingKey,
|
|
525
|
+
startDate: params.periodStart,
|
|
526
|
+
endDate: params.periodEnd,
|
|
527
|
+
format: 'json',
|
|
528
|
+
},
|
|
529
|
+
encryptedTransactions
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
const transactions = historyExport.data as DecryptedTransaction[]
|
|
533
|
+
|
|
534
|
+
// Compute summary statistics
|
|
535
|
+
const summary = this.computeSummaryStats(transactions)
|
|
536
|
+
|
|
537
|
+
// Generate report based on type
|
|
538
|
+
let reportData: Record<string, unknown>
|
|
539
|
+
|
|
540
|
+
switch (params.reportType) {
|
|
541
|
+
case 'transaction_summary':
|
|
542
|
+
reportData = this.generateTransactionSummary(transactions, params.includeDetails)
|
|
543
|
+
break
|
|
544
|
+
case 'audit_trail':
|
|
545
|
+
reportData = this.generateAuditTrail(transactions)
|
|
546
|
+
break
|
|
547
|
+
case 'risk_assessment':
|
|
548
|
+
reportData = this.generateRiskAssessment(transactions)
|
|
549
|
+
break
|
|
550
|
+
case 'regulatory_filing':
|
|
551
|
+
reportData = this.generateRegulatoryFiling(transactions)
|
|
552
|
+
break
|
|
553
|
+
case 'tax_report':
|
|
554
|
+
reportData = this.generateTaxReport(transactions)
|
|
555
|
+
break
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Format output
|
|
559
|
+
let data: string | Record<string, unknown>
|
|
560
|
+
|
|
561
|
+
switch (params.format) {
|
|
562
|
+
case 'json':
|
|
563
|
+
data = reportData
|
|
564
|
+
break
|
|
565
|
+
case 'csv':
|
|
566
|
+
data = this.formatReportAsCsv(reportData)
|
|
567
|
+
break
|
|
568
|
+
case 'pdf':
|
|
569
|
+
data = this.formatReportAsPdfBase64(reportData)
|
|
570
|
+
break
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const report: ComplianceReport = {
|
|
574
|
+
id: this.generateId('rpt'),
|
|
575
|
+
type: params.reportType,
|
|
576
|
+
generatedAt: new Date(),
|
|
577
|
+
period: { start: params.periodStart, end: params.periodEnd },
|
|
578
|
+
summary,
|
|
579
|
+
data,
|
|
580
|
+
format: params.format,
|
|
581
|
+
checksum: this.computeChecksum(data),
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
this.reports.set(report.id, report)
|
|
585
|
+
|
|
586
|
+
return report
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Get a previously generated report
|
|
591
|
+
*
|
|
592
|
+
* @param reportId - Report ID
|
|
593
|
+
* @returns Report or null
|
|
594
|
+
*/
|
|
595
|
+
getReport(reportId: string): ComplianceReport | null {
|
|
596
|
+
return this.reports.get(reportId) ?? null
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Verify API connectivity to Fireblocks
|
|
601
|
+
*
|
|
602
|
+
* @returns Whether connection is successful
|
|
603
|
+
*/
|
|
604
|
+
async verifyConnection(): Promise<boolean> {
|
|
605
|
+
try {
|
|
606
|
+
// In production, this would make an authenticated API call
|
|
607
|
+
// For now, validate configuration
|
|
608
|
+
return !!(this.apiKey && this.secretKey && this.vaultAccountId)
|
|
609
|
+
} catch {
|
|
610
|
+
return false
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Validate viewing key format
|
|
616
|
+
*/
|
|
617
|
+
private isValidViewingKey(viewingKey: ViewingKey): boolean {
|
|
618
|
+
if (!viewingKey.key || !viewingKey.path || !viewingKey.hash) {
|
|
619
|
+
return false
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Must be hex string starting with 0x
|
|
623
|
+
if (!viewingKey.key.startsWith('0x') || viewingKey.key.length < 66) {
|
|
624
|
+
return false
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return true
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Validate scope configuration
|
|
632
|
+
*/
|
|
633
|
+
private isValidScope(scope: ViewingKeyScope): boolean {
|
|
634
|
+
if (scope.startDate && scope.endDate && scope.startDate > scope.endDate) {
|
|
635
|
+
return false
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
if (scope.minAmount !== undefined && scope.maxAmount !== undefined) {
|
|
639
|
+
if (scope.minAmount > scope.maxAmount) {
|
|
640
|
+
return false
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return true
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Compute viewing key hash
|
|
649
|
+
*/
|
|
650
|
+
private computeViewingKeyHash(viewingKey: ViewingKey): Hash {
|
|
651
|
+
const keyBytes = hexToBytes(viewingKey.key.slice(2))
|
|
652
|
+
const hash = sha256(keyBytes)
|
|
653
|
+
return `0x${bytesToHex(hash)}` as Hash
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Generate unique ID
|
|
658
|
+
*/
|
|
659
|
+
private generateId(prefix: string): string {
|
|
660
|
+
const timestamp = Date.now().toString(36)
|
|
661
|
+
const random = Math.random().toString(36).slice(2, 10)
|
|
662
|
+
return `${prefix}_${timestamp}_${random}`
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Map decrypted data to transaction format
|
|
667
|
+
*/
|
|
668
|
+
private mapToDecryptedTransaction(
|
|
669
|
+
decrypted: TransactionData,
|
|
670
|
+
_encrypted: EncryptedTransaction
|
|
671
|
+
): DecryptedTransaction {
|
|
672
|
+
return {
|
|
673
|
+
id: this.generateId('tx'),
|
|
674
|
+
type: 'transfer', // Default type
|
|
675
|
+
chain: 'solana', // Would be extracted from metadata
|
|
676
|
+
sender: decrypted.sender,
|
|
677
|
+
recipient: decrypted.recipient,
|
|
678
|
+
amount: decrypted.amount.toString(),
|
|
679
|
+
asset: 'USDC', // Would be extracted from metadata
|
|
680
|
+
timestamp: new Date(decrypted.timestamp),
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Format transactions as CSV
|
|
686
|
+
*/
|
|
687
|
+
private formatAsCsv(transactions: DecryptedTransaction[]): string {
|
|
688
|
+
const headers = [
|
|
689
|
+
'id',
|
|
690
|
+
'type',
|
|
691
|
+
'chain',
|
|
692
|
+
'sender',
|
|
693
|
+
'recipient',
|
|
694
|
+
'amount',
|
|
695
|
+
'asset',
|
|
696
|
+
'timestamp',
|
|
697
|
+
'riskScore',
|
|
698
|
+
]
|
|
699
|
+
|
|
700
|
+
const rows = transactions.map(tx =>
|
|
701
|
+
[
|
|
702
|
+
tx.id,
|
|
703
|
+
tx.type,
|
|
704
|
+
tx.chain,
|
|
705
|
+
tx.sender,
|
|
706
|
+
tx.recipient,
|
|
707
|
+
tx.amount,
|
|
708
|
+
tx.asset,
|
|
709
|
+
tx.timestamp.toISOString(),
|
|
710
|
+
tx.riskScore ?? '',
|
|
711
|
+
].join(',')
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
return [headers.join(','), ...rows].join('\n')
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Format transactions as PDF (base64)
|
|
719
|
+
*/
|
|
720
|
+
private formatAsPdfBase64(transactions: DecryptedTransaction[]): string {
|
|
721
|
+
// In production, would use a PDF library
|
|
722
|
+
// For now, return a placeholder
|
|
723
|
+
const content = JSON.stringify({
|
|
724
|
+
title: 'SIP Protocol Transaction History',
|
|
725
|
+
generatedAt: new Date().toISOString(),
|
|
726
|
+
transactionCount: transactions.length,
|
|
727
|
+
transactions: transactions.map(tx => ({
|
|
728
|
+
id: tx.id,
|
|
729
|
+
type: tx.type,
|
|
730
|
+
amount: tx.amount,
|
|
731
|
+
timestamp: tx.timestamp,
|
|
732
|
+
})),
|
|
733
|
+
})
|
|
734
|
+
|
|
735
|
+
return Buffer.from(content).toString('base64')
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Compute summary statistics
|
|
740
|
+
*/
|
|
741
|
+
private computeSummaryStats(transactions: DecryptedTransaction[]): ComplianceReport['summary'] {
|
|
742
|
+
const uniqueCounterparties = new Set([
|
|
743
|
+
...transactions.map(tx => tx.sender),
|
|
744
|
+
...transactions.map(tx => tx.recipient),
|
|
745
|
+
])
|
|
746
|
+
|
|
747
|
+
const riskScores = transactions
|
|
748
|
+
.filter(tx => tx.riskScore !== undefined)
|
|
749
|
+
.map(tx => tx.riskScore!)
|
|
750
|
+
|
|
751
|
+
const totalVolume = transactions.reduce(
|
|
752
|
+
(sum, tx) => sum + BigInt(tx.amount),
|
|
753
|
+
0n
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
return {
|
|
757
|
+
totalTransactions: transactions.length,
|
|
758
|
+
totalVolume: totalVolume.toString(),
|
|
759
|
+
uniqueCounterparties: uniqueCounterparties.size,
|
|
760
|
+
averageRiskScore: riskScores.length > 0
|
|
761
|
+
? riskScores.reduce((a, b) => a + b, 0) / riskScores.length
|
|
762
|
+
: 0,
|
|
763
|
+
flaggedTransactions: transactions.filter(tx => (tx.riskScore ?? 0) >= 70).length,
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Generate transaction summary report
|
|
769
|
+
*/
|
|
770
|
+
private generateTransactionSummary(
|
|
771
|
+
transactions: DecryptedTransaction[],
|
|
772
|
+
includeDetails?: boolean
|
|
773
|
+
): Record<string, unknown> {
|
|
774
|
+
const byType = new Map<TransactionType, number>()
|
|
775
|
+
const byChain = new Map<string, number>()
|
|
776
|
+
const byAsset = new Map<string, bigint>()
|
|
777
|
+
|
|
778
|
+
for (const tx of transactions) {
|
|
779
|
+
byType.set(tx.type, (byType.get(tx.type) ?? 0) + 1)
|
|
780
|
+
byChain.set(tx.chain, (byChain.get(tx.chain) ?? 0) + 1)
|
|
781
|
+
byAsset.set(tx.asset, (byAsset.get(tx.asset) ?? 0n) + BigInt(tx.amount))
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
return {
|
|
785
|
+
reportType: 'transaction_summary',
|
|
786
|
+
period: {
|
|
787
|
+
start: transactions[0]?.timestamp,
|
|
788
|
+
end: transactions[transactions.length - 1]?.timestamp,
|
|
789
|
+
},
|
|
790
|
+
breakdown: {
|
|
791
|
+
byType: Object.fromEntries(byType),
|
|
792
|
+
byChain: Object.fromEntries(byChain),
|
|
793
|
+
byAsset: Object.fromEntries(
|
|
794
|
+
Array.from(byAsset.entries()).map(([k, v]) => [k, v.toString()])
|
|
795
|
+
),
|
|
796
|
+
},
|
|
797
|
+
transactions: includeDetails ? transactions : undefined,
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Generate audit trail report
|
|
803
|
+
*/
|
|
804
|
+
private generateAuditTrail(transactions: DecryptedTransaction[]): Record<string, unknown> {
|
|
805
|
+
return {
|
|
806
|
+
reportType: 'audit_trail',
|
|
807
|
+
entries: transactions.map(tx => ({
|
|
808
|
+
timestamp: tx.timestamp,
|
|
809
|
+
action: tx.type,
|
|
810
|
+
from: tx.sender,
|
|
811
|
+
to: tx.recipient,
|
|
812
|
+
amount: tx.amount,
|
|
813
|
+
asset: tx.asset,
|
|
814
|
+
chain: tx.chain,
|
|
815
|
+
id: tx.id,
|
|
816
|
+
})),
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Generate risk assessment report
|
|
822
|
+
*/
|
|
823
|
+
private generateRiskAssessment(transactions: DecryptedTransaction[]): Record<string, unknown> {
|
|
824
|
+
const highRisk = transactions.filter(tx => (tx.riskScore ?? 0) >= 70)
|
|
825
|
+
const mediumRisk = transactions.filter(tx =>
|
|
826
|
+
(tx.riskScore ?? 0) >= 30 && (tx.riskScore ?? 0) < 70
|
|
827
|
+
)
|
|
828
|
+
const lowRisk = transactions.filter(tx => (tx.riskScore ?? 0) < 30)
|
|
829
|
+
|
|
830
|
+
return {
|
|
831
|
+
reportType: 'risk_assessment',
|
|
832
|
+
distribution: {
|
|
833
|
+
high: highRisk.length,
|
|
834
|
+
medium: mediumRisk.length,
|
|
835
|
+
low: lowRisk.length,
|
|
836
|
+
},
|
|
837
|
+
flaggedTransactions: highRisk.map(tx => ({
|
|
838
|
+
id: tx.id,
|
|
839
|
+
riskScore: tx.riskScore,
|
|
840
|
+
reason: 'High value transaction', // Would be more detailed in production
|
|
841
|
+
})),
|
|
842
|
+
recommendations: [
|
|
843
|
+
'Review high-risk transactions for suspicious activity',
|
|
844
|
+
'Verify counterparty identities for flagged addresses',
|
|
845
|
+
],
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Generate regulatory filing report
|
|
851
|
+
*/
|
|
852
|
+
private generateRegulatoryFiling(transactions: DecryptedTransaction[]): Record<string, unknown> {
|
|
853
|
+
return {
|
|
854
|
+
reportType: 'regulatory_filing',
|
|
855
|
+
filingType: 'SAR_PREP', // Suspicious Activity Report preparation
|
|
856
|
+
totalTransactions: transactions.length,
|
|
857
|
+
flaggedForReview: transactions.filter(tx => (tx.riskScore ?? 0) >= 70).length,
|
|
858
|
+
volumeAnalysis: this.computeSummaryStats(transactions),
|
|
859
|
+
attachments: ['transaction_detail', 'risk_assessment'],
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Generate tax report
|
|
865
|
+
*/
|
|
866
|
+
private generateTaxReport(transactions: DecryptedTransaction[]): Record<string, unknown> {
|
|
867
|
+
// Group by asset for cost basis tracking
|
|
868
|
+
const byAsset = new Map<string, DecryptedTransaction[]>()
|
|
869
|
+
|
|
870
|
+
for (const tx of transactions) {
|
|
871
|
+
const existing = byAsset.get(tx.asset) ?? []
|
|
872
|
+
existing.push(tx)
|
|
873
|
+
byAsset.set(tx.asset, existing)
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
return {
|
|
877
|
+
reportType: 'tax_report',
|
|
878
|
+
taxYear: transactions[0]?.timestamp.getFullYear(),
|
|
879
|
+
assets: Array.from(byAsset.entries()).map(([asset, txs]) => ({
|
|
880
|
+
asset,
|
|
881
|
+
transactionCount: txs.length,
|
|
882
|
+
totalVolume: txs.reduce((sum, tx) => sum + BigInt(tx.amount), 0n).toString(),
|
|
883
|
+
// Would include cost basis calculations in production
|
|
884
|
+
})),
|
|
885
|
+
disclaimer: 'This report is for informational purposes only. Consult a tax professional.',
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Format report as CSV
|
|
891
|
+
*/
|
|
892
|
+
private formatReportAsCsv(report: Record<string, unknown>): string {
|
|
893
|
+
return JSON.stringify(report) // Simplified for demo
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Format report as PDF (base64)
|
|
898
|
+
*/
|
|
899
|
+
private formatReportAsPdfBase64(report: Record<string, unknown>): string {
|
|
900
|
+
return Buffer.from(JSON.stringify(report)).toString('base64')
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Compute checksum for data integrity
|
|
905
|
+
*/
|
|
906
|
+
private computeChecksum(data: string | unknown): Hash {
|
|
907
|
+
const str = typeof data === 'string' ? data : JSON.stringify(data)
|
|
908
|
+
const hash = sha256(new TextEncoder().encode(str))
|
|
909
|
+
return `0x${bytesToHex(hash)}` as Hash
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Create a Fireblocks viewing key client
|
|
915
|
+
*
|
|
916
|
+
* @param config - Fireblocks configuration
|
|
917
|
+
* @returns Configured client
|
|
918
|
+
*/
|
|
919
|
+
export function createFireblocksClient(config: FireblocksConfig): FireblocksViewingKeyClient {
|
|
920
|
+
return new FireblocksViewingKeyClient(config)
|
|
921
|
+
}
|