@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,605 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana Privacy Adapter
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates privacy operations for Solana same-chain transactions.
|
|
5
|
+
* Provides a unified interface for stealth transfers, scanning, and claiming.
|
|
6
|
+
*
|
|
7
|
+
* @module chains/solana/privacy-adapter
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Connection, PublicKey, type Transaction, type VersionedTransaction } from '@solana/web3.js'
|
|
11
|
+
import type { StealthMetaAddress, HexString } from '@sip-protocol/types'
|
|
12
|
+
import {
|
|
13
|
+
generateEd25519StealthAddress,
|
|
14
|
+
decodeStealthMetaAddress,
|
|
15
|
+
ed25519PublicKeyToSolanaAddress,
|
|
16
|
+
generateEd25519StealthMetaAddress,
|
|
17
|
+
} from '../../stealth'
|
|
18
|
+
import { sendPrivateSPLTransfer, estimatePrivateTransferFee, hasTokenAccount } from './transfer'
|
|
19
|
+
import { scanForPayments, claimStealthPayment, getStealthBalance } from './scan'
|
|
20
|
+
import {
|
|
21
|
+
StealthScanner,
|
|
22
|
+
createStealthScanner,
|
|
23
|
+
type ScanRecipient,
|
|
24
|
+
type DetectedPayment,
|
|
25
|
+
type HistoricalScanOptions,
|
|
26
|
+
} from './stealth-scanner'
|
|
27
|
+
import {
|
|
28
|
+
generateEphemeralKeypair,
|
|
29
|
+
generateManagedEphemeralKeypair,
|
|
30
|
+
type EphemeralKeypair,
|
|
31
|
+
type ManagedEphemeralKeypair,
|
|
32
|
+
} from './ephemeral-keys'
|
|
33
|
+
import { createProvider, type SolanaRPCProvider, type ProviderType, type ProviderConfig } from './providers'
|
|
34
|
+
import type {
|
|
35
|
+
SolanaPrivateTransferResult,
|
|
36
|
+
SolanaScanResult,
|
|
37
|
+
SolanaClaimResult,
|
|
38
|
+
} from './types'
|
|
39
|
+
import type { SolanaCluster } from './constants'
|
|
40
|
+
|
|
41
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Configuration for SolanaPrivacyAdapter
|
|
45
|
+
*/
|
|
46
|
+
export interface SolanaPrivacyAdapterConfig {
|
|
47
|
+
/**
|
|
48
|
+
* Solana RPC connection
|
|
49
|
+
*/
|
|
50
|
+
connection: Connection
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Network cluster
|
|
54
|
+
* @default 'mainnet-beta'
|
|
55
|
+
*/
|
|
56
|
+
cluster?: SolanaCluster
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Optional RPC provider for efficient queries
|
|
60
|
+
*/
|
|
61
|
+
provider?: SolanaRPCProvider
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Provider type to auto-create if provider not specified
|
|
65
|
+
*/
|
|
66
|
+
providerType?: ProviderType
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Provider configuration (API key, etc.)
|
|
70
|
+
*/
|
|
71
|
+
providerConfig?: ProviderConfig
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Parameters for creating a shielded transfer
|
|
76
|
+
*/
|
|
77
|
+
export interface ShieldedTransferParams {
|
|
78
|
+
/**
|
|
79
|
+
* Sender's public key
|
|
80
|
+
*/
|
|
81
|
+
sender: PublicKey
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Sender's token account (ATA)
|
|
85
|
+
*/
|
|
86
|
+
senderTokenAccount: PublicKey
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Recipient's stealth meta-address
|
|
90
|
+
* Can be a StealthMetaAddress object or encoded string (sip:solana:...)
|
|
91
|
+
*/
|
|
92
|
+
recipient: StealthMetaAddress | string
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* SPL token mint address
|
|
96
|
+
*/
|
|
97
|
+
mint: PublicKey
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Amount to transfer (in token's smallest unit)
|
|
101
|
+
*/
|
|
102
|
+
amount: bigint
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Function to sign the transaction
|
|
106
|
+
*/
|
|
107
|
+
signTransaction: <T extends Transaction | VersionedTransaction>(tx: T) => Promise<T>
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Parameters for scanning with the adapter
|
|
112
|
+
*/
|
|
113
|
+
export interface AdapterScanParams {
|
|
114
|
+
/**
|
|
115
|
+
* Viewing private key (hex)
|
|
116
|
+
*/
|
|
117
|
+
viewingPrivateKey: HexString
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Spending public key (hex)
|
|
121
|
+
*/
|
|
122
|
+
spendingPublicKey: HexString
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Scan options (slots, limits, etc.)
|
|
126
|
+
*/
|
|
127
|
+
options?: HistoricalScanOptions
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Parameters for claiming with the adapter
|
|
132
|
+
*/
|
|
133
|
+
export interface AdapterClaimParams {
|
|
134
|
+
/**
|
|
135
|
+
* Detected payment to claim
|
|
136
|
+
*/
|
|
137
|
+
payment: DetectedPayment
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Viewing private key (hex)
|
|
141
|
+
*/
|
|
142
|
+
viewingPrivateKey: HexString
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Spending private key (hex)
|
|
146
|
+
*/
|
|
147
|
+
spendingPrivateKey: HexString
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Destination address for claimed funds
|
|
151
|
+
*/
|
|
152
|
+
destinationAddress: string
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Privacy adapter state
|
|
157
|
+
*/
|
|
158
|
+
export interface PrivacyAdapterState {
|
|
159
|
+
/**
|
|
160
|
+
* Whether the adapter is initialized
|
|
161
|
+
*/
|
|
162
|
+
isInitialized: boolean
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Current cluster
|
|
166
|
+
*/
|
|
167
|
+
cluster: SolanaCluster
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Whether a provider is available
|
|
171
|
+
*/
|
|
172
|
+
hasProvider: boolean
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Number of recipients in the scanner
|
|
176
|
+
*/
|
|
177
|
+
scannerRecipientCount: number
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Whether actively scanning (subscribed)
|
|
181
|
+
*/
|
|
182
|
+
isScanning: boolean
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ─── SolanaPrivacyAdapter Class ───────────────────────────────────────────────
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Solana Privacy Adapter
|
|
189
|
+
*
|
|
190
|
+
* Provides a unified interface for privacy operations on Solana:
|
|
191
|
+
* - Shielded transfers to stealth addresses
|
|
192
|
+
* - Payment scanning and detection
|
|
193
|
+
* - Claiming detected payments
|
|
194
|
+
* - Meta-address and keypair generation
|
|
195
|
+
*
|
|
196
|
+
* @example Basic usage
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const adapter = new SolanaPrivacyAdapter({
|
|
199
|
+
* connection,
|
|
200
|
+
* cluster: 'mainnet-beta',
|
|
201
|
+
* providerType: 'helius',
|
|
202
|
+
* providerConfig: { apiKey: '...' },
|
|
203
|
+
* })
|
|
204
|
+
*
|
|
205
|
+
* // Generate meta-address for recipient
|
|
206
|
+
* const { metaAddress, viewingPrivateKey, spendingPrivateKey } =
|
|
207
|
+
* adapter.generateMetaAddress('Primary Wallet')
|
|
208
|
+
*
|
|
209
|
+
* // Send shielded transfer
|
|
210
|
+
* const result = await adapter.sendShieldedTransfer({
|
|
211
|
+
* sender: wallet.publicKey,
|
|
212
|
+
* senderTokenAccount: walletATA,
|
|
213
|
+
* recipient: recipientMetaAddress,
|
|
214
|
+
* mint: USDC_MINT,
|
|
215
|
+
* amount: 5_000_000n,
|
|
216
|
+
* signTransaction: wallet.signTransaction,
|
|
217
|
+
* })
|
|
218
|
+
*
|
|
219
|
+
* // Scan for incoming payments
|
|
220
|
+
* const payments = await adapter.scanForPayments({
|
|
221
|
+
* viewingPrivateKey,
|
|
222
|
+
* spendingPublicKey: metaAddress.spendingKey,
|
|
223
|
+
* })
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* @example Real-time scanning
|
|
227
|
+
* ```typescript
|
|
228
|
+
* // Add recipient for scanning
|
|
229
|
+
* adapter.addScanRecipient({
|
|
230
|
+
* viewingPrivateKey,
|
|
231
|
+
* spendingPublicKey,
|
|
232
|
+
* label: 'Main Wallet',
|
|
233
|
+
* })
|
|
234
|
+
*
|
|
235
|
+
* // Subscribe to real-time payments
|
|
236
|
+
* adapter.subscribeToPayments(
|
|
237
|
+
* (payment) => console.log('Received:', payment),
|
|
238
|
+
* (error) => console.error('Error:', error)
|
|
239
|
+
* )
|
|
240
|
+
*
|
|
241
|
+
* // Later: stop scanning
|
|
242
|
+
* await adapter.unsubscribeFromPayments()
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export class SolanaPrivacyAdapter {
|
|
246
|
+
private connection: Connection
|
|
247
|
+
private cluster: SolanaCluster
|
|
248
|
+
private provider?: SolanaRPCProvider
|
|
249
|
+
private scanner: StealthScanner
|
|
250
|
+
private initialized: boolean = false
|
|
251
|
+
|
|
252
|
+
constructor(config: SolanaPrivacyAdapterConfig) {
|
|
253
|
+
this.connection = config.connection
|
|
254
|
+
this.cluster = config.cluster ?? 'mainnet-beta'
|
|
255
|
+
|
|
256
|
+
// Initialize provider
|
|
257
|
+
if (config.provider) {
|
|
258
|
+
this.provider = config.provider
|
|
259
|
+
} else if (config.providerType && config.providerConfig) {
|
|
260
|
+
this.provider = createProvider(config.providerType, config.providerConfig)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Initialize scanner
|
|
264
|
+
this.scanner = createStealthScanner({
|
|
265
|
+
connection: this.connection,
|
|
266
|
+
provider: this.provider,
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
this.initialized = true
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ─── Meta-Address Generation ────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Generate a new stealth meta-address
|
|
276
|
+
*
|
|
277
|
+
* Creates a new keypair for receiving private payments.
|
|
278
|
+
* The meta-address can be shared publicly; only the private keys
|
|
279
|
+
* enable scanning and claiming.
|
|
280
|
+
*
|
|
281
|
+
* @param label - Optional label for the address
|
|
282
|
+
* @returns Meta-address and private keys
|
|
283
|
+
*/
|
|
284
|
+
generateMetaAddress(label?: string): {
|
|
285
|
+
metaAddress: StealthMetaAddress
|
|
286
|
+
viewingPrivateKey: HexString
|
|
287
|
+
spendingPrivateKey: HexString
|
|
288
|
+
} {
|
|
289
|
+
const result = generateEd25519StealthMetaAddress('solana', label)
|
|
290
|
+
return {
|
|
291
|
+
metaAddress: result.metaAddress,
|
|
292
|
+
viewingPrivateKey: result.viewingPrivateKey,
|
|
293
|
+
spendingPrivateKey: result.spendingPrivateKey,
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Parse an encoded meta-address string
|
|
299
|
+
*
|
|
300
|
+
* @param encoded - Encoded meta-address (sip:solana:...)
|
|
301
|
+
* @returns Decoded meta-address
|
|
302
|
+
*/
|
|
303
|
+
parseMetaAddress(encoded: string): StealthMetaAddress {
|
|
304
|
+
return decodeStealthMetaAddress(encoded)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ─── Ephemeral Keys ─────────────────────────────────────────────────────────
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Generate an ephemeral keypair for a single transfer
|
|
311
|
+
*
|
|
312
|
+
* @returns Ephemeral keypair
|
|
313
|
+
*/
|
|
314
|
+
generateEphemeralKeypair(): EphemeralKeypair {
|
|
315
|
+
return generateEphemeralKeypair()
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Generate a managed ephemeral keypair with auto-disposal
|
|
320
|
+
*
|
|
321
|
+
* @returns Managed ephemeral keypair
|
|
322
|
+
*/
|
|
323
|
+
generateManagedEphemeralKeypair(): ManagedEphemeralKeypair {
|
|
324
|
+
return generateManagedEphemeralKeypair()
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ─── Stealth Address Resolution ─────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Resolve a meta-address to a one-time stealth address
|
|
331
|
+
*
|
|
332
|
+
* Generates a fresh stealth address for the recipient.
|
|
333
|
+
* Each call produces a different, unlinkable address.
|
|
334
|
+
*
|
|
335
|
+
* @param recipient - Recipient's meta-address
|
|
336
|
+
* @returns Stealth address details
|
|
337
|
+
*/
|
|
338
|
+
resolveStealthAddress(recipient: StealthMetaAddress | string): {
|
|
339
|
+
stealthAddress: string
|
|
340
|
+
stealthAddressHex: HexString
|
|
341
|
+
ephemeralPublicKey: string
|
|
342
|
+
ephemeralPublicKeyHex: HexString
|
|
343
|
+
viewTag: number
|
|
344
|
+
sharedSecret: HexString
|
|
345
|
+
} {
|
|
346
|
+
const metaAddress = typeof recipient === 'string'
|
|
347
|
+
? decodeStealthMetaAddress(recipient)
|
|
348
|
+
: recipient
|
|
349
|
+
|
|
350
|
+
const { stealthAddress, sharedSecret } = generateEd25519StealthAddress(metaAddress)
|
|
351
|
+
|
|
352
|
+
const stealthAddressBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.address)
|
|
353
|
+
const ephemeralPublicKeyBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.ephemeralPublicKey)
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
stealthAddress: stealthAddressBase58,
|
|
357
|
+
stealthAddressHex: stealthAddress.address,
|
|
358
|
+
ephemeralPublicKey: ephemeralPublicKeyBase58,
|
|
359
|
+
ephemeralPublicKeyHex: stealthAddress.ephemeralPublicKey,
|
|
360
|
+
viewTag: stealthAddress.viewTag,
|
|
361
|
+
sharedSecret,
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ─── Shielded Transfers ─────────────────────────────────────────────────────
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Send a shielded SPL token transfer
|
|
369
|
+
*
|
|
370
|
+
* Transfers tokens to a stealth address with on-chain announcement
|
|
371
|
+
* for recipient scanning.
|
|
372
|
+
*
|
|
373
|
+
* @param params - Transfer parameters
|
|
374
|
+
* @returns Transfer result
|
|
375
|
+
*/
|
|
376
|
+
async sendShieldedTransfer(
|
|
377
|
+
params: ShieldedTransferParams
|
|
378
|
+
): Promise<SolanaPrivateTransferResult> {
|
|
379
|
+
const recipient = typeof params.recipient === 'string'
|
|
380
|
+
? decodeStealthMetaAddress(params.recipient)
|
|
381
|
+
: params.recipient
|
|
382
|
+
|
|
383
|
+
return sendPrivateSPLTransfer({
|
|
384
|
+
connection: this.connection,
|
|
385
|
+
sender: params.sender,
|
|
386
|
+
senderTokenAccount: params.senderTokenAccount,
|
|
387
|
+
recipientMetaAddress: recipient,
|
|
388
|
+
mint: params.mint,
|
|
389
|
+
amount: params.amount,
|
|
390
|
+
signTransaction: params.signTransaction,
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Estimate fee for a shielded transfer
|
|
396
|
+
*
|
|
397
|
+
* @param needsATACreation - Whether ATA needs to be created
|
|
398
|
+
* @returns Estimated fee in lamports
|
|
399
|
+
*/
|
|
400
|
+
async estimateTransferFee(needsATACreation: boolean = true): Promise<bigint> {
|
|
401
|
+
return estimatePrivateTransferFee(this.connection, needsATACreation)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Check if a stealth address has a token account
|
|
406
|
+
*
|
|
407
|
+
* @param stealthAddress - Stealth address (base58)
|
|
408
|
+
* @param mint - Token mint
|
|
409
|
+
* @returns True if token account exists
|
|
410
|
+
*/
|
|
411
|
+
async hasTokenAccount(stealthAddress: string, mint: PublicKey): Promise<boolean> {
|
|
412
|
+
return hasTokenAccount(this.connection, stealthAddress, mint)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ─── Payment Scanning ───────────────────────────────────────────────────────
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Scan for incoming stealth payments (one-time)
|
|
419
|
+
*
|
|
420
|
+
* @param params - Scan parameters
|
|
421
|
+
* @returns Detected payments
|
|
422
|
+
*/
|
|
423
|
+
async scanForPayments(params: AdapterScanParams): Promise<SolanaScanResult[]> {
|
|
424
|
+
return scanForPayments({
|
|
425
|
+
connection: this.connection,
|
|
426
|
+
viewingPrivateKey: params.viewingPrivateKey,
|
|
427
|
+
spendingPublicKey: params.spendingPublicKey,
|
|
428
|
+
provider: this.provider,
|
|
429
|
+
fromSlot: params.options?.fromSlot,
|
|
430
|
+
toSlot: params.options?.toSlot,
|
|
431
|
+
limit: params.options?.limit,
|
|
432
|
+
})
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Add a recipient to the continuous scanner
|
|
437
|
+
*
|
|
438
|
+
* @param recipient - Recipient keys and label
|
|
439
|
+
*/
|
|
440
|
+
addScanRecipient(recipient: ScanRecipient): void {
|
|
441
|
+
this.scanner.addRecipient(recipient)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Remove a recipient from the scanner
|
|
446
|
+
*
|
|
447
|
+
* @param label - Recipient label to remove
|
|
448
|
+
*/
|
|
449
|
+
removeScanRecipient(label: string): void {
|
|
450
|
+
this.scanner.removeRecipient(label)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Get all scan recipients
|
|
455
|
+
*/
|
|
456
|
+
getScanRecipients(): ScanRecipient[] {
|
|
457
|
+
return this.scanner.getRecipients()
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Clear all scan recipients
|
|
462
|
+
*/
|
|
463
|
+
clearScanRecipients(): void {
|
|
464
|
+
this.scanner.clearRecipients()
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Scan historical transactions
|
|
469
|
+
*
|
|
470
|
+
* @param options - Scan options
|
|
471
|
+
* @returns Scan result with detected payments
|
|
472
|
+
*/
|
|
473
|
+
async scanHistorical(options?: HistoricalScanOptions) {
|
|
474
|
+
return this.scanner.scanHistorical(options)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Subscribe to real-time payment detection
|
|
479
|
+
*
|
|
480
|
+
* @param onPayment - Callback for detected payments
|
|
481
|
+
* @param onError - Callback for errors
|
|
482
|
+
*/
|
|
483
|
+
subscribeToPayments(
|
|
484
|
+
onPayment: (payment: DetectedPayment) => void,
|
|
485
|
+
onError?: (error: Error) => void
|
|
486
|
+
): void {
|
|
487
|
+
this.scanner.subscribe(onPayment, onError)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Unsubscribe from real-time payments
|
|
492
|
+
*/
|
|
493
|
+
async unsubscribeFromPayments(): Promise<void> {
|
|
494
|
+
await this.scanner.unsubscribe()
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Check if currently subscribed to payments
|
|
499
|
+
*/
|
|
500
|
+
isSubscribedToPayments(): boolean {
|
|
501
|
+
return this.scanner.isSubscribed()
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ─── Payment Claiming ───────────────────────────────────────────────────────
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Claim a detected payment
|
|
508
|
+
*
|
|
509
|
+
* Derives the stealth private key and transfers funds to the destination.
|
|
510
|
+
*
|
|
511
|
+
* @param params - Claim parameters
|
|
512
|
+
* @returns Claim result
|
|
513
|
+
*/
|
|
514
|
+
async claimPayment(params: AdapterClaimParams): Promise<SolanaClaimResult> {
|
|
515
|
+
return claimStealthPayment({
|
|
516
|
+
connection: this.connection,
|
|
517
|
+
stealthAddress: params.payment.stealthAddress,
|
|
518
|
+
ephemeralPublicKey: params.payment.ephemeralPublicKey,
|
|
519
|
+
viewingPrivateKey: params.viewingPrivateKey,
|
|
520
|
+
spendingPrivateKey: params.spendingPrivateKey,
|
|
521
|
+
destinationAddress: params.destinationAddress,
|
|
522
|
+
mint: new PublicKey(params.payment.mint),
|
|
523
|
+
})
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Get balance for a stealth address
|
|
528
|
+
*
|
|
529
|
+
* @param stealthAddress - Stealth address (base58)
|
|
530
|
+
* @param mint - Token mint
|
|
531
|
+
* @returns Token balance
|
|
532
|
+
*/
|
|
533
|
+
async getStealthBalance(stealthAddress: string, mint: PublicKey): Promise<bigint> {
|
|
534
|
+
return getStealthBalance(this.connection, stealthAddress, mint, this.provider)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// ─── State & Utilities ──────────────────────────────────────────────────────
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Get adapter state
|
|
541
|
+
*/
|
|
542
|
+
getState(): PrivacyAdapterState {
|
|
543
|
+
return {
|
|
544
|
+
isInitialized: this.initialized,
|
|
545
|
+
cluster: this.cluster,
|
|
546
|
+
hasProvider: !!this.provider,
|
|
547
|
+
scannerRecipientCount: this.scanner.getRecipients().length,
|
|
548
|
+
isScanning: this.scanner.isSubscribed(),
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Get the underlying connection
|
|
554
|
+
*/
|
|
555
|
+
getConnection(): Connection {
|
|
556
|
+
return this.connection
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Get the RPC provider (if configured)
|
|
561
|
+
*/
|
|
562
|
+
getProvider(): SolanaRPCProvider | undefined {
|
|
563
|
+
return this.provider
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Get the current cluster
|
|
568
|
+
*/
|
|
569
|
+
getCluster(): SolanaCluster {
|
|
570
|
+
return this.cluster
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Dispose of the adapter and clean up resources
|
|
575
|
+
*/
|
|
576
|
+
async dispose(): Promise<void> {
|
|
577
|
+
await this.scanner.unsubscribe()
|
|
578
|
+
this.scanner.clearRecipients()
|
|
579
|
+
this.initialized = false
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// ─── Factory Function ─────────────────────────────────────────────────────────
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Create a new Solana privacy adapter
|
|
587
|
+
*
|
|
588
|
+
* @param config - Adapter configuration
|
|
589
|
+
* @returns Configured privacy adapter
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* ```typescript
|
|
593
|
+
* const adapter = createSolanaPrivacyAdapter({
|
|
594
|
+
* connection: new Connection('https://api.mainnet-beta.solana.com'),
|
|
595
|
+
* cluster: 'mainnet-beta',
|
|
596
|
+
* providerType: 'helius',
|
|
597
|
+
* providerConfig: { apiKey: process.env.HELIUS_API_KEY },
|
|
598
|
+
* })
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
export function createSolanaPrivacyAdapter(
|
|
602
|
+
config: SolanaPrivacyAdapterConfig
|
|
603
|
+
): SolanaPrivacyAdapter {
|
|
604
|
+
return new SolanaPrivacyAdapter(config)
|
|
605
|
+
}
|