@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,702 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NEAR Wallet Selector Privacy Integration
|
|
3
|
+
*
|
|
4
|
+
* Integrates SIP privacy features with NEAR Wallet Selector,
|
|
5
|
+
* enabling privacy transactions across all compatible wallets.
|
|
6
|
+
*
|
|
7
|
+
* @example Basic usage
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { setupWalletSelector } from '@near-wallet-selector/core'
|
|
10
|
+
* import { setupModal } from '@near-wallet-selector/modal-ui'
|
|
11
|
+
* import { createPrivacyWalletSelector } from '@sip-protocol/sdk'
|
|
12
|
+
*
|
|
13
|
+
* // Setup standard wallet selector
|
|
14
|
+
* const selector = await setupWalletSelector({
|
|
15
|
+
* network: 'testnet',
|
|
16
|
+
* modules: [setupMyNearWallet(), setupMeteorWallet()],
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* // Wrap with privacy support
|
|
20
|
+
* const privacySelector = createPrivacyWalletSelector(selector, {
|
|
21
|
+
* network: 'testnet',
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // Generate stealth meta-address for receiving
|
|
25
|
+
* const { metaAddress, encoded } = await privacySelector.generateStealthMetaAddress()
|
|
26
|
+
*
|
|
27
|
+
* // Send private transfer
|
|
28
|
+
* const result = await privacySelector.sendPrivateTransfer({
|
|
29
|
+
* recipientMetaAddress: encoded,
|
|
30
|
+
* amount: '1000000000000000000000000', // 1 NEAR
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @packageDocumentation
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { sha256 } from '@noble/hashes/sha2'
|
|
38
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
|
|
39
|
+
import { ed25519 } from '@noble/curves/ed25519'
|
|
40
|
+
import type { HexString, StealthMetaAddress, StealthAddress } from '@sip-protocol/types'
|
|
41
|
+
import type { NEARNetwork } from '../../chains/near/constants'
|
|
42
|
+
import {
|
|
43
|
+
generateNEARStealthAddress,
|
|
44
|
+
deriveNEARStealthPrivateKey,
|
|
45
|
+
checkNEARStealthAddress,
|
|
46
|
+
encodeNEARStealthMetaAddress,
|
|
47
|
+
parseNEARStealthMetaAddress,
|
|
48
|
+
} from '../../chains/near/stealth'
|
|
49
|
+
import { buildPrivateTransfer } from '../../chains/near/implicit-account'
|
|
50
|
+
|
|
51
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* NEAR Wallet Selector interface (minimal type for compatibility)
|
|
55
|
+
* This matches the core interface from @near-wallet-selector/core
|
|
56
|
+
*/
|
|
57
|
+
export interface WalletSelector {
|
|
58
|
+
/** Get the currently selected wallet */
|
|
59
|
+
wallet(): Promise<Wallet | null>
|
|
60
|
+
/** Check if connected */
|
|
61
|
+
isSignedIn(): boolean
|
|
62
|
+
/** Get account ID */
|
|
63
|
+
getAccounts(): Promise<Array<{ accountId: string; publicKey?: string }>>
|
|
64
|
+
/** Subscribe to state changes */
|
|
65
|
+
on(event: string, callback: (state: unknown) => void): () => void
|
|
66
|
+
/** Get current state */
|
|
67
|
+
store: {
|
|
68
|
+
getState(): WalletSelectorState
|
|
69
|
+
observable: {
|
|
70
|
+
subscribe(callback: (state: WalletSelectorState) => void): { unsubscribe(): void }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Wallet Selector state
|
|
77
|
+
*/
|
|
78
|
+
export interface WalletSelectorState {
|
|
79
|
+
accounts: Array<{ accountId: string; publicKey?: string }>
|
|
80
|
+
selectedWalletId: string | null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Wallet interface from Wallet Selector
|
|
85
|
+
*/
|
|
86
|
+
export interface Wallet {
|
|
87
|
+
id: string
|
|
88
|
+
type: string
|
|
89
|
+
metadata: {
|
|
90
|
+
name: string
|
|
91
|
+
description?: string
|
|
92
|
+
iconUrl?: string
|
|
93
|
+
}
|
|
94
|
+
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<WalletTransactionResult>
|
|
95
|
+
signAndSendTransactions?(params: SignAndSendTransactionsParams): Promise<WalletTransactionResult[]>
|
|
96
|
+
signMessage?(params: SignMessageParams): Promise<SignedMessage>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Transaction parameters for Wallet Selector
|
|
101
|
+
*/
|
|
102
|
+
export interface SignAndSendTransactionParams {
|
|
103
|
+
signerId?: string
|
|
104
|
+
receiverId: string
|
|
105
|
+
actions: WalletAction[]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Batch transaction parameters
|
|
110
|
+
*/
|
|
111
|
+
export interface SignAndSendTransactionsParams {
|
|
112
|
+
transactions: SignAndSendTransactionParams[]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Wallet action types
|
|
117
|
+
*/
|
|
118
|
+
export interface WalletAction {
|
|
119
|
+
type: 'Transfer' | 'FunctionCall' | 'AddKey' | 'DeleteKey' | 'DeleteAccount'
|
|
120
|
+
params: Record<string, unknown>
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Transaction result from wallet
|
|
125
|
+
*/
|
|
126
|
+
export interface WalletTransactionResult {
|
|
127
|
+
transaction: {
|
|
128
|
+
hash: string
|
|
129
|
+
signerId: string
|
|
130
|
+
receiverId: string
|
|
131
|
+
}
|
|
132
|
+
receipts?: unknown[]
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sign message parameters
|
|
137
|
+
*/
|
|
138
|
+
export interface SignMessageParams {
|
|
139
|
+
message: string
|
|
140
|
+
recipient: string
|
|
141
|
+
nonce: Buffer
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Signed message result
|
|
146
|
+
*/
|
|
147
|
+
export interface SignedMessage {
|
|
148
|
+
signature: string
|
|
149
|
+
publicKey: string
|
|
150
|
+
accountId: string
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Privacy Wallet Selector configuration
|
|
155
|
+
*/
|
|
156
|
+
export interface PrivacyWalletSelectorConfig {
|
|
157
|
+
/** NEAR network */
|
|
158
|
+
network: NEARNetwork
|
|
159
|
+
/** Custom RPC URL */
|
|
160
|
+
rpcUrl?: string
|
|
161
|
+
/** Auto-derive privacy keys on connect */
|
|
162
|
+
autoDerive?: boolean
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Privacy key pair derived from wallet
|
|
167
|
+
*/
|
|
168
|
+
export interface PrivacyKeyPair {
|
|
169
|
+
spendingPrivateKey: HexString
|
|
170
|
+
spendingPublicKey: HexString
|
|
171
|
+
viewingPrivateKey: HexString
|
|
172
|
+
viewingPublicKey: HexString
|
|
173
|
+
derivationLabel: string
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Stealth address result with account ID
|
|
178
|
+
*/
|
|
179
|
+
export interface StealthAddressResult {
|
|
180
|
+
stealthAddress: StealthAddress
|
|
181
|
+
stealthAccountId: string
|
|
182
|
+
ephemeralPublicKey: HexString
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Private transfer parameters
|
|
187
|
+
*/
|
|
188
|
+
export interface PrivateTransferParams {
|
|
189
|
+
/** Recipient's stealth meta-address (encoded or object) */
|
|
190
|
+
recipientMetaAddress: string | StealthMetaAddress
|
|
191
|
+
/** Amount in yoctoNEAR */
|
|
192
|
+
amount: string | bigint
|
|
193
|
+
/** Optional memo */
|
|
194
|
+
memo?: string
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Private transfer result
|
|
199
|
+
*/
|
|
200
|
+
export interface PrivateTransferResult {
|
|
201
|
+
/** Transaction hash */
|
|
202
|
+
txHash: string
|
|
203
|
+
/** Stealth address created */
|
|
204
|
+
stealthAddress: StealthAddress
|
|
205
|
+
/** Stealth account ID (implicit account) */
|
|
206
|
+
stealthAccountId: string
|
|
207
|
+
/** Announcement memo for recipient scanning */
|
|
208
|
+
announcementMemo: string
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Wallet privacy capabilities
|
|
213
|
+
*/
|
|
214
|
+
export interface WalletPrivacyCapabilities {
|
|
215
|
+
/** Wallet ID */
|
|
216
|
+
walletId: string
|
|
217
|
+
/** Wallet name */
|
|
218
|
+
walletName: string
|
|
219
|
+
/** Supports message signing (required for key derivation) */
|
|
220
|
+
supportsMessageSigning: boolean
|
|
221
|
+
/** Supports transaction signing */
|
|
222
|
+
supportsTransactionSigning: boolean
|
|
223
|
+
/** Supports batch transactions */
|
|
224
|
+
supportsBatchTransactions: boolean
|
|
225
|
+
/** Overall privacy support level */
|
|
226
|
+
privacySupport: 'full' | 'partial' | 'none'
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Viewing key export
|
|
231
|
+
*/
|
|
232
|
+
export interface ViewingKeyExport {
|
|
233
|
+
network: NEARNetwork
|
|
234
|
+
viewingPublicKey: HexString
|
|
235
|
+
viewingPrivateKey: HexString
|
|
236
|
+
spendingPublicKey: HexString
|
|
237
|
+
accountId: string
|
|
238
|
+
createdAt: number
|
|
239
|
+
label?: string
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ─── Privacy Wallet Selector ──────────────────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Privacy-enhanced Wallet Selector wrapper
|
|
246
|
+
*
|
|
247
|
+
* Wraps the standard NEAR Wallet Selector to add privacy capabilities.
|
|
248
|
+
*/
|
|
249
|
+
export class PrivacyWalletSelector {
|
|
250
|
+
private selector: WalletSelector
|
|
251
|
+
private config: PrivacyWalletSelectorConfig
|
|
252
|
+
private privacyKeys: PrivacyKeyPair | null = null
|
|
253
|
+
private stealthAddresses: Map<string, StealthAddressResult> = new Map()
|
|
254
|
+
private connectionListeners: Set<(connected: boolean) => void> = new Set()
|
|
255
|
+
|
|
256
|
+
constructor(selector: WalletSelector, config: PrivacyWalletSelectorConfig) {
|
|
257
|
+
this.selector = selector
|
|
258
|
+
this.config = config
|
|
259
|
+
|
|
260
|
+
// Subscribe to wallet selector state changes
|
|
261
|
+
this.selector.store.observable.subscribe((state) => {
|
|
262
|
+
const isConnected = state.accounts.length > 0
|
|
263
|
+
this.connectionListeners.forEach((listener) => listener(isConnected))
|
|
264
|
+
|
|
265
|
+
// Clear privacy keys on disconnect
|
|
266
|
+
if (!isConnected) {
|
|
267
|
+
this.privacyKeys = null
|
|
268
|
+
this.stealthAddresses.clear()
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ─── Connection State ───────────────────────────────────────────────────────
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Check if wallet is connected
|
|
277
|
+
*/
|
|
278
|
+
isConnected(): boolean {
|
|
279
|
+
return this.selector.isSignedIn()
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Get connected account ID
|
|
284
|
+
*/
|
|
285
|
+
async getAccountId(): Promise<string | null> {
|
|
286
|
+
const accounts = await this.selector.getAccounts()
|
|
287
|
+
return accounts[0]?.accountId ?? null
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Get connected wallet
|
|
292
|
+
*/
|
|
293
|
+
async getWallet(): Promise<Wallet | null> {
|
|
294
|
+
return this.selector.wallet()
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Subscribe to connection state changes
|
|
299
|
+
*/
|
|
300
|
+
onConnectionChange(callback: (connected: boolean) => void): () => void {
|
|
301
|
+
this.connectionListeners.add(callback)
|
|
302
|
+
return () => this.connectionListeners.delete(callback)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ─── Wallet Capabilities ────────────────────────────────────────────────────
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Detect privacy capabilities of the current wallet
|
|
309
|
+
*/
|
|
310
|
+
async detectCapabilities(): Promise<WalletPrivacyCapabilities | null> {
|
|
311
|
+
const wallet = await this.selector.wallet()
|
|
312
|
+
if (!wallet) return null
|
|
313
|
+
|
|
314
|
+
const supportsMessageSigning = typeof wallet.signMessage === 'function'
|
|
315
|
+
const supportsTransactionSigning = typeof wallet.signAndSendTransaction === 'function'
|
|
316
|
+
const supportsBatchTransactions = typeof wallet.signAndSendTransactions === 'function'
|
|
317
|
+
|
|
318
|
+
// Determine privacy support level
|
|
319
|
+
let privacySupport: 'full' | 'partial' | 'none' = 'none'
|
|
320
|
+
if (supportsMessageSigning && supportsTransactionSigning) {
|
|
321
|
+
privacySupport = supportsBatchTransactions ? 'full' : 'partial'
|
|
322
|
+
} else if (supportsTransactionSigning) {
|
|
323
|
+
privacySupport = 'partial'
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
walletId: wallet.id,
|
|
328
|
+
walletName: wallet.metadata.name,
|
|
329
|
+
supportsMessageSigning,
|
|
330
|
+
supportsTransactionSigning,
|
|
331
|
+
supportsBatchTransactions,
|
|
332
|
+
privacySupport,
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Check if current wallet supports full privacy operations
|
|
338
|
+
*/
|
|
339
|
+
async supportsPrivacy(): Promise<boolean> {
|
|
340
|
+
const capabilities = await this.detectCapabilities()
|
|
341
|
+
return capabilities?.privacySupport !== 'none'
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ─── Privacy Key Management ─────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Derive privacy keys from wallet
|
|
348
|
+
*
|
|
349
|
+
* Uses message signing to deterministically derive privacy keys
|
|
350
|
+
* without exposing the wallet's seed phrase.
|
|
351
|
+
*/
|
|
352
|
+
async derivePrivacyKeys(label: string = 'default'): Promise<PrivacyKeyPair> {
|
|
353
|
+
const wallet = await this.selector.wallet()
|
|
354
|
+
if (!wallet) {
|
|
355
|
+
throw new Error('No wallet connected')
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (!wallet.signMessage) {
|
|
359
|
+
throw new Error('Wallet does not support message signing for key derivation')
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const accountId = await this.getAccountId()
|
|
363
|
+
if (!accountId) {
|
|
364
|
+
throw new Error('No account connected')
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Create derivation message
|
|
368
|
+
const derivationPath = `sip/near/${this.config.network}/${label}`
|
|
369
|
+
const nonce = Buffer.from(sha256(new TextEncoder().encode(derivationPath)).slice(0, 32))
|
|
370
|
+
|
|
371
|
+
// Sign the derivation message
|
|
372
|
+
const signed = await wallet.signMessage({
|
|
373
|
+
message: `SIP Privacy Key Derivation: ${derivationPath}`,
|
|
374
|
+
recipient: accountId,
|
|
375
|
+
nonce,
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
// Derive keys from signature
|
|
379
|
+
const entropy = hexToBytes(signed.signature.replace(/^0x/, '').slice(0, 128))
|
|
380
|
+
|
|
381
|
+
// Derive spending key
|
|
382
|
+
const spendingEntropy = sha256(new Uint8Array([...entropy.slice(0, 32), 0x01]))
|
|
383
|
+
const spendingPrivateKey = clampScalar(spendingEntropy)
|
|
384
|
+
const spendingPublicKey = ed25519.getPublicKey(spendingPrivateKey)
|
|
385
|
+
|
|
386
|
+
// Derive viewing key
|
|
387
|
+
const viewingEntropy = sha256(new Uint8Array([...entropy.slice(32, 64), 0x02]))
|
|
388
|
+
const viewingPrivateKey = clampScalar(viewingEntropy)
|
|
389
|
+
const viewingPublicKey = ed25519.getPublicKey(viewingPrivateKey)
|
|
390
|
+
|
|
391
|
+
const keyPair: PrivacyKeyPair = {
|
|
392
|
+
spendingPrivateKey: `0x${bytesToHex(spendingPrivateKey)}` as HexString,
|
|
393
|
+
spendingPublicKey: `0x${bytesToHex(spendingPublicKey)}` as HexString,
|
|
394
|
+
viewingPrivateKey: `0x${bytesToHex(viewingPrivateKey)}` as HexString,
|
|
395
|
+
viewingPublicKey: `0x${bytesToHex(viewingPublicKey)}` as HexString,
|
|
396
|
+
derivationLabel: label,
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
this.privacyKeys = keyPair
|
|
400
|
+
return keyPair
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Check if privacy keys are derived
|
|
405
|
+
*/
|
|
406
|
+
hasPrivacyKeys(): boolean {
|
|
407
|
+
return this.privacyKeys !== null
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Get derived privacy keys
|
|
412
|
+
*/
|
|
413
|
+
getPrivacyKeys(): PrivacyKeyPair | null {
|
|
414
|
+
return this.privacyKeys
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// ─── Stealth Address Operations ─────────────────────────────────────────────
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Generate a stealth meta-address for receiving private payments
|
|
421
|
+
*/
|
|
422
|
+
async generateStealthMetaAddress(label?: string): Promise<{
|
|
423
|
+
metaAddress: StealthMetaAddress
|
|
424
|
+
encoded: string
|
|
425
|
+
viewingPrivateKey: HexString
|
|
426
|
+
spendingPrivateKey: HexString
|
|
427
|
+
}> {
|
|
428
|
+
const keys = this.privacyKeys ?? await this.derivePrivacyKeys(label)
|
|
429
|
+
|
|
430
|
+
const metaAddress: StealthMetaAddress = {
|
|
431
|
+
chain: 'near',
|
|
432
|
+
spendingKey: keys.spendingPublicKey,
|
|
433
|
+
viewingKey: keys.viewingPublicKey,
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const encoded = encodeNEARStealthMetaAddress(metaAddress)
|
|
437
|
+
|
|
438
|
+
return {
|
|
439
|
+
metaAddress,
|
|
440
|
+
encoded,
|
|
441
|
+
viewingPrivateKey: keys.viewingPrivateKey,
|
|
442
|
+
spendingPrivateKey: keys.spendingPrivateKey,
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Generate a one-time stealth address from a meta-address
|
|
448
|
+
*/
|
|
449
|
+
generateStealthAddress(metaAddress: string | StealthMetaAddress): StealthAddressResult {
|
|
450
|
+
const meta = typeof metaAddress === 'string'
|
|
451
|
+
? parseNEARStealthMetaAddress(metaAddress)
|
|
452
|
+
: metaAddress
|
|
453
|
+
|
|
454
|
+
const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(meta)
|
|
455
|
+
|
|
456
|
+
const result: StealthAddressResult = {
|
|
457
|
+
stealthAddress,
|
|
458
|
+
stealthAccountId: implicitAccountId,
|
|
459
|
+
ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
this.stealthAddresses.set(implicitAccountId, result)
|
|
463
|
+
return result
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Check if a stealth address belongs to this wallet
|
|
468
|
+
*/
|
|
469
|
+
async checkStealthAddress(stealthAddress: StealthAddress): Promise<boolean> {
|
|
470
|
+
const keys = this.privacyKeys ?? await this.derivePrivacyKeys()
|
|
471
|
+
|
|
472
|
+
return checkNEARStealthAddress(
|
|
473
|
+
stealthAddress,
|
|
474
|
+
keys.spendingPublicKey,
|
|
475
|
+
keys.viewingPrivateKey
|
|
476
|
+
)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Derive private key for a stealth address
|
|
481
|
+
*/
|
|
482
|
+
async deriveStealthPrivateKey(stealthAddress: StealthAddress): Promise<HexString> {
|
|
483
|
+
const keys = this.privacyKeys ?? await this.derivePrivacyKeys()
|
|
484
|
+
|
|
485
|
+
const isOwner = await this.checkStealthAddress(stealthAddress)
|
|
486
|
+
if (!isOwner) {
|
|
487
|
+
throw new Error('Stealth address does not belong to this wallet')
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const recovery = deriveNEARStealthPrivateKey(
|
|
491
|
+
stealthAddress,
|
|
492
|
+
keys.spendingPrivateKey,
|
|
493
|
+
keys.viewingPrivateKey
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
return recovery.privateKey
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ─── Private Transfers ──────────────────────────────────────────────────────
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Send a private NEAR transfer
|
|
503
|
+
*/
|
|
504
|
+
async sendPrivateTransfer(params: PrivateTransferParams): Promise<PrivateTransferResult> {
|
|
505
|
+
const wallet = await this.selector.wallet()
|
|
506
|
+
if (!wallet) {
|
|
507
|
+
throw new Error('No wallet connected')
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const accountId = await this.getAccountId()
|
|
511
|
+
if (!accountId) {
|
|
512
|
+
throw new Error('No account connected')
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// Parse recipient meta-address
|
|
516
|
+
const recipientMeta = typeof params.recipientMetaAddress === 'string'
|
|
517
|
+
? parseNEARStealthMetaAddress(params.recipientMetaAddress)
|
|
518
|
+
: params.recipientMetaAddress
|
|
519
|
+
|
|
520
|
+
// Build the transfer (generates stealth address internally)
|
|
521
|
+
const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
|
|
522
|
+
const transfer = buildPrivateTransfer(recipientMeta, amount)
|
|
523
|
+
|
|
524
|
+
// Get stealth address info from the transfer result
|
|
525
|
+
const { stealthAddress, stealthAccountId: implicitAccountId, announcementMemo } = transfer
|
|
526
|
+
|
|
527
|
+
// Convert actions to wallet selector format
|
|
528
|
+
const walletActions: WalletAction[] = transfer.actions.map((action) => ({
|
|
529
|
+
type: action.type,
|
|
530
|
+
params: action.params as unknown as Record<string, unknown>,
|
|
531
|
+
}))
|
|
532
|
+
|
|
533
|
+
// Send transaction
|
|
534
|
+
const result = await wallet.signAndSendTransaction({
|
|
535
|
+
signerId: accountId,
|
|
536
|
+
receiverId: implicitAccountId,
|
|
537
|
+
actions: walletActions,
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
return {
|
|
541
|
+
txHash: result.transaction.hash,
|
|
542
|
+
stealthAddress,
|
|
543
|
+
stealthAccountId: implicitAccountId,
|
|
544
|
+
announcementMemo,
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Send multiple private transfers in a batch
|
|
550
|
+
*/
|
|
551
|
+
async sendBatchPrivateTransfers(
|
|
552
|
+
transfers: PrivateTransferParams[]
|
|
553
|
+
): Promise<PrivateTransferResult[]> {
|
|
554
|
+
const wallet = await this.selector.wallet()
|
|
555
|
+
if (!wallet) {
|
|
556
|
+
throw new Error('No wallet connected')
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (!wallet.signAndSendTransactions) {
|
|
560
|
+
throw new Error('Wallet does not support batch transactions')
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const accountId = await this.getAccountId()
|
|
564
|
+
if (!accountId) {
|
|
565
|
+
throw new Error('No account connected')
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Build all transfers
|
|
569
|
+
const transactions: SignAndSendTransactionParams[] = []
|
|
570
|
+
const transferResults: Array<{
|
|
571
|
+
stealthAddress: StealthAddress
|
|
572
|
+
stealthAccountId: string
|
|
573
|
+
announcementMemo: string
|
|
574
|
+
}> = []
|
|
575
|
+
|
|
576
|
+
for (const params of transfers) {
|
|
577
|
+
const recipientMeta = typeof params.recipientMetaAddress === 'string'
|
|
578
|
+
? parseNEARStealthMetaAddress(params.recipientMetaAddress)
|
|
579
|
+
: params.recipientMetaAddress
|
|
580
|
+
|
|
581
|
+
const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
|
|
582
|
+
const transfer = buildPrivateTransfer(recipientMeta, amount)
|
|
583
|
+
|
|
584
|
+
const { stealthAddress, stealthAccountId, announcementMemo } = transfer
|
|
585
|
+
|
|
586
|
+
const walletActions: WalletAction[] = transfer.actions.map((action) => ({
|
|
587
|
+
type: action.type,
|
|
588
|
+
params: action.params as unknown as Record<string, unknown>,
|
|
589
|
+
}))
|
|
590
|
+
|
|
591
|
+
transactions.push({
|
|
592
|
+
signerId: accountId,
|
|
593
|
+
receiverId: stealthAccountId,
|
|
594
|
+
actions: walletActions,
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
transferResults.push({
|
|
598
|
+
stealthAddress,
|
|
599
|
+
stealthAccountId,
|
|
600
|
+
announcementMemo,
|
|
601
|
+
})
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Send batch
|
|
605
|
+
const results = await wallet.signAndSendTransactions({ transactions })
|
|
606
|
+
|
|
607
|
+
return results.map((result, index) => ({
|
|
608
|
+
txHash: result.transaction.hash,
|
|
609
|
+
...transferResults[index],
|
|
610
|
+
}))
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// ─── Viewing Key Export ─────────────────────────────────────────────────────
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Export viewing key for compliance/audit sharing
|
|
617
|
+
*/
|
|
618
|
+
async exportViewingKey(label?: string): Promise<ViewingKeyExport> {
|
|
619
|
+
const keys = this.privacyKeys ?? await this.derivePrivacyKeys(label)
|
|
620
|
+
const accountId = await this.getAccountId()
|
|
621
|
+
|
|
622
|
+
if (!accountId) {
|
|
623
|
+
throw new Error('No account connected')
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return {
|
|
627
|
+
network: this.config.network,
|
|
628
|
+
viewingPublicKey: keys.viewingPublicKey,
|
|
629
|
+
viewingPrivateKey: keys.viewingPrivateKey,
|
|
630
|
+
spendingPublicKey: keys.spendingPublicKey,
|
|
631
|
+
accountId,
|
|
632
|
+
createdAt: Date.now(),
|
|
633
|
+
label,
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// ─── Utility Methods ────────────────────────────────────────────────────────
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Get all tracked stealth addresses
|
|
641
|
+
*/
|
|
642
|
+
getStealthAddresses(): Map<string, StealthAddressResult> {
|
|
643
|
+
return new Map(this.stealthAddresses)
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Get the underlying wallet selector
|
|
648
|
+
*/
|
|
649
|
+
getSelector(): WalletSelector {
|
|
650
|
+
return this.selector
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Get configuration
|
|
655
|
+
*/
|
|
656
|
+
getConfig(): PrivacyWalletSelectorConfig {
|
|
657
|
+
return { ...this.config }
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// ─── Factory Functions ────────────────────────────────────────────────────────
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Create a privacy-enhanced wallet selector wrapper
|
|
665
|
+
*/
|
|
666
|
+
export function createPrivacyWalletSelector(
|
|
667
|
+
selector: WalletSelector,
|
|
668
|
+
config: PrivacyWalletSelectorConfig
|
|
669
|
+
): PrivacyWalletSelector {
|
|
670
|
+
return new PrivacyWalletSelector(selector, config)
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Create privacy wallet selector for mainnet
|
|
675
|
+
*/
|
|
676
|
+
export function createMainnetPrivacySelector(
|
|
677
|
+
selector: WalletSelector
|
|
678
|
+
): PrivacyWalletSelector {
|
|
679
|
+
return new PrivacyWalletSelector(selector, { network: 'mainnet' })
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Create privacy wallet selector for testnet
|
|
684
|
+
*/
|
|
685
|
+
export function createTestnetPrivacySelector(
|
|
686
|
+
selector: WalletSelector
|
|
687
|
+
): PrivacyWalletSelector {
|
|
688
|
+
return new PrivacyWalletSelector(selector, { network: 'testnet' })
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// ─── Utility Functions ────────────────────────────────────────────────────────
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Clamp a 32-byte scalar for ed25519
|
|
695
|
+
*/
|
|
696
|
+
function clampScalar(bytes: Uint8Array): Uint8Array {
|
|
697
|
+
const clamped = new Uint8Array(bytes)
|
|
698
|
+
clamped[0] &= 248
|
|
699
|
+
clamped[31] &= 127
|
|
700
|
+
clamped[31] |= 64
|
|
701
|
+
return clamped
|
|
702
|
+
}
|