@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,584 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ethereum Stealth Meta-Address Registry Client
|
|
3
|
+
*
|
|
4
|
+
* ERC-6538 compliant registry for publishing and discovering
|
|
5
|
+
* stealth meta-addresses on Ethereum.
|
|
6
|
+
*
|
|
7
|
+
* @module chains/ethereum/registry
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { HexString } from '@sip-protocol/types'
|
|
11
|
+
import {
|
|
12
|
+
type EthereumNetwork,
|
|
13
|
+
EIP5564_REGISTRY_ADDRESS,
|
|
14
|
+
SECP256K1_SCHEME_ID,
|
|
15
|
+
isValidEthAddress,
|
|
16
|
+
} from './constants'
|
|
17
|
+
import {
|
|
18
|
+
parseEthereumStealthMetaAddress,
|
|
19
|
+
encodeEthereumStealthMetaAddress,
|
|
20
|
+
type EthereumStealthMetaAddress,
|
|
21
|
+
} from './stealth'
|
|
22
|
+
|
|
23
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Registry entry for a stealth meta-address
|
|
27
|
+
*/
|
|
28
|
+
export interface StealthRegistryEntry {
|
|
29
|
+
/**
|
|
30
|
+
* Owner's Ethereum address
|
|
31
|
+
*/
|
|
32
|
+
owner: HexString
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Scheme ID (1 = secp256k1)
|
|
36
|
+
*/
|
|
37
|
+
schemeId: number
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Stealth meta-address
|
|
41
|
+
*/
|
|
42
|
+
metaAddress: EthereumStealthMetaAddress
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Encoded meta-address string
|
|
46
|
+
*/
|
|
47
|
+
encoded: string
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Block number when registered
|
|
51
|
+
*/
|
|
52
|
+
blockNumber?: number
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Timestamp when registered
|
|
56
|
+
*/
|
|
57
|
+
timestamp?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Options for registry lookup
|
|
62
|
+
*/
|
|
63
|
+
export interface RegistryLookupOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Scheme ID to filter by (default: SECP256K1_SCHEME_ID)
|
|
66
|
+
*/
|
|
67
|
+
schemeId?: number
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Block number to query at (latest if not specified)
|
|
71
|
+
*/
|
|
72
|
+
blockNumber?: number | 'latest'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Options for registry registration
|
|
77
|
+
*/
|
|
78
|
+
export interface RegistryRegisterOptions {
|
|
79
|
+
/**
|
|
80
|
+
* Scheme ID (default: SECP256K1_SCHEME_ID)
|
|
81
|
+
*/
|
|
82
|
+
schemeId?: number
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Gas limit override
|
|
86
|
+
*/
|
|
87
|
+
gasLimit?: bigint
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Result of registry query
|
|
92
|
+
*/
|
|
93
|
+
export interface RegistryQueryResult {
|
|
94
|
+
/**
|
|
95
|
+
* Whether an entry was found
|
|
96
|
+
*/
|
|
97
|
+
found: boolean
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The registry entry (if found)
|
|
101
|
+
*/
|
|
102
|
+
entry?: StealthRegistryEntry
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Raw bytes from registry (for debugging)
|
|
106
|
+
*/
|
|
107
|
+
rawData?: HexString
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Built transaction for registry operations
|
|
112
|
+
*/
|
|
113
|
+
export interface RegistryTransaction {
|
|
114
|
+
/**
|
|
115
|
+
* Target contract address
|
|
116
|
+
*/
|
|
117
|
+
to: HexString
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Transaction data
|
|
121
|
+
*/
|
|
122
|
+
data: HexString
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Value (should be 0 for registry operations)
|
|
126
|
+
*/
|
|
127
|
+
value: bigint
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Suggested gas limit
|
|
131
|
+
*/
|
|
132
|
+
gasLimit: bigint
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Registry cache entry
|
|
137
|
+
*/
|
|
138
|
+
interface CacheEntry {
|
|
139
|
+
entry: StealthRegistryEntry | null
|
|
140
|
+
timestamp: number
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Registry contract ABI selectors
|
|
147
|
+
*/
|
|
148
|
+
const REGISTRY_SELECTORS = {
|
|
149
|
+
/**
|
|
150
|
+
* registerKeys(uint256 schemeId, bytes stealthMetaAddress)
|
|
151
|
+
*/
|
|
152
|
+
registerKeys: '0x4a8c1fb4',
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* registerKeysOnBehalf(address registrant, uint256 schemeId, bytes signature, bytes stealthMetaAddress)
|
|
156
|
+
*/
|
|
157
|
+
registerKeysOnBehalf: '0x6ea7b7ef',
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* stealthMetaAddressOf(address registrant, uint256 schemeId) returns (bytes)
|
|
161
|
+
*/
|
|
162
|
+
stealthMetaAddressOf: '0x3c154045',
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* incrementNonce() - for signature replay protection
|
|
166
|
+
*/
|
|
167
|
+
incrementNonce: '0xd09de08a',
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* nonceOf(address registrant) returns (uint256)
|
|
171
|
+
*/
|
|
172
|
+
nonceOf: '0x70ae92d2',
|
|
173
|
+
} as const
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Cache duration (5 minutes)
|
|
177
|
+
*/
|
|
178
|
+
const CACHE_DURATION = 5 * 60 * 1000
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Network-specific registry addresses
|
|
182
|
+
* Falls back to default EIP5564_REGISTRY_ADDRESS
|
|
183
|
+
*/
|
|
184
|
+
const REGISTRY_ADDRESSES: Partial<Record<EthereumNetwork, HexString>> = {
|
|
185
|
+
mainnet: EIP5564_REGISTRY_ADDRESS as HexString,
|
|
186
|
+
sepolia: EIP5564_REGISTRY_ADDRESS as HexString,
|
|
187
|
+
// Other networks may have different addresses
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ─── Registry Client Class ──────────────────────────────────────────────────
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* ERC-6538 Stealth Meta-Address Registry Client
|
|
194
|
+
*
|
|
195
|
+
* Provides methods to lookup and register stealth meta-addresses on-chain.
|
|
196
|
+
*
|
|
197
|
+
* @example Basic usage
|
|
198
|
+
* ```typescript
|
|
199
|
+
* const registry = new RegistryClient('mainnet')
|
|
200
|
+
*
|
|
201
|
+
* // Lookup meta-address
|
|
202
|
+
* const result = await registry.lookup('0x...')
|
|
203
|
+
* if (result.found) {
|
|
204
|
+
* console.log(result.entry?.encoded)
|
|
205
|
+
* }
|
|
206
|
+
*
|
|
207
|
+
* // Build registration transaction
|
|
208
|
+
* const tx = registry.buildRegisterTransaction(metaAddress)
|
|
209
|
+
* // Sign and submit tx externally
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export class RegistryClient {
|
|
213
|
+
private network: EthereumNetwork
|
|
214
|
+
private registryAddress: HexString
|
|
215
|
+
private cache: Map<string, CacheEntry> = new Map()
|
|
216
|
+
private cacheEnabled: boolean
|
|
217
|
+
|
|
218
|
+
constructor(
|
|
219
|
+
network: EthereumNetwork = 'mainnet',
|
|
220
|
+
options?: {
|
|
221
|
+
registryAddress?: HexString
|
|
222
|
+
enableCache?: boolean
|
|
223
|
+
}
|
|
224
|
+
) {
|
|
225
|
+
this.network = network
|
|
226
|
+
this.registryAddress = options?.registryAddress ??
|
|
227
|
+
(REGISTRY_ADDRESSES[network] ?? EIP5564_REGISTRY_ADDRESS) as HexString
|
|
228
|
+
this.cacheEnabled = options?.enableCache ?? true
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ─── Query Methods ───────────────────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Build call data for looking up a meta-address
|
|
235
|
+
*
|
|
236
|
+
* Use this to make an eth_call to the registry.
|
|
237
|
+
*
|
|
238
|
+
* @param address - Ethereum address to lookup
|
|
239
|
+
* @param options - Lookup options
|
|
240
|
+
* @returns Call data for eth_call
|
|
241
|
+
*/
|
|
242
|
+
buildLookupCallData(
|
|
243
|
+
address: HexString,
|
|
244
|
+
options: RegistryLookupOptions = {}
|
|
245
|
+
): { to: HexString; data: HexString } {
|
|
246
|
+
if (!isValidEthAddress(address)) {
|
|
247
|
+
throw new Error(`Invalid Ethereum address: ${address}`)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const schemeId = options.schemeId ?? SECP256K1_SCHEME_ID
|
|
251
|
+
|
|
252
|
+
// Encode: stealthMetaAddressOf(address,uint256)
|
|
253
|
+
const addressParam = address.slice(2).padStart(64, '0')
|
|
254
|
+
const schemeIdParam = schemeId.toString(16).padStart(64, '0')
|
|
255
|
+
const data = `${REGISTRY_SELECTORS.stealthMetaAddressOf}${addressParam}${schemeIdParam}` as HexString
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
to: this.registryAddress,
|
|
259
|
+
data,
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Parse the response from a lookup call
|
|
265
|
+
*
|
|
266
|
+
* @param response - Raw response from eth_call
|
|
267
|
+
* @param owner - The address that was looked up
|
|
268
|
+
* @returns Parsed registry entry or null
|
|
269
|
+
*/
|
|
270
|
+
parseLookupResponse(
|
|
271
|
+
response: HexString,
|
|
272
|
+
owner: HexString
|
|
273
|
+
): StealthRegistryEntry | null {
|
|
274
|
+
// Remove 0x prefix
|
|
275
|
+
const data = response.slice(2)
|
|
276
|
+
|
|
277
|
+
// Empty response or zero response means not registered
|
|
278
|
+
if (!data || data === '0' || data === '' || /^0+$/.test(data)) {
|
|
279
|
+
return null
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
// Response is ABI-encoded bytes
|
|
284
|
+
// Format: offset (32 bytes) + length (32 bytes) + data
|
|
285
|
+
if (data.length < 128) {
|
|
286
|
+
return null
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Skip offset (first 32 bytes)
|
|
290
|
+
// Get length (next 32 bytes)
|
|
291
|
+
const lengthHex = data.slice(64, 128)
|
|
292
|
+
const length = parseInt(lengthHex, 16)
|
|
293
|
+
|
|
294
|
+
if (length === 0) {
|
|
295
|
+
return null
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Get actual data
|
|
299
|
+
const metaAddressBytes = data.slice(128, 128 + length * 2)
|
|
300
|
+
|
|
301
|
+
// Meta-address format: spendingKey (33 bytes) + viewingKey (33 bytes)
|
|
302
|
+
if (metaAddressBytes.length !== 132) {
|
|
303
|
+
// 66 * 2 = 132 hex chars
|
|
304
|
+
return null
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const spendingKey = `0x${metaAddressBytes.slice(0, 66)}` as HexString
|
|
308
|
+
const viewingKey = `0x${metaAddressBytes.slice(66)}` as HexString
|
|
309
|
+
|
|
310
|
+
const metaAddress: EthereumStealthMetaAddress = {
|
|
311
|
+
chain: 'ethereum',
|
|
312
|
+
schemeId: SECP256K1_SCHEME_ID,
|
|
313
|
+
spendingKey,
|
|
314
|
+
viewingKey,
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const encoded = encodeEthereumStealthMetaAddress(metaAddress)
|
|
318
|
+
|
|
319
|
+
return {
|
|
320
|
+
owner,
|
|
321
|
+
schemeId: SECP256K1_SCHEME_ID,
|
|
322
|
+
metaAddress,
|
|
323
|
+
encoded,
|
|
324
|
+
}
|
|
325
|
+
} catch {
|
|
326
|
+
return null
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Get a cached lookup result
|
|
332
|
+
*
|
|
333
|
+
* @param address - Address to check cache for
|
|
334
|
+
* @returns Cached entry or undefined
|
|
335
|
+
*/
|
|
336
|
+
getCached(address: HexString): StealthRegistryEntry | null | undefined {
|
|
337
|
+
if (!this.cacheEnabled) return undefined
|
|
338
|
+
|
|
339
|
+
const key = this.getCacheKey(address)
|
|
340
|
+
const cached = this.cache.get(key)
|
|
341
|
+
|
|
342
|
+
if (!cached) return undefined
|
|
343
|
+
if (Date.now() - cached.timestamp > CACHE_DURATION) {
|
|
344
|
+
this.cache.delete(key)
|
|
345
|
+
return undefined
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return cached.entry
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Cache a lookup result
|
|
353
|
+
*
|
|
354
|
+
* @param address - Address that was looked up
|
|
355
|
+
* @param entry - Result to cache (null if not found)
|
|
356
|
+
*/
|
|
357
|
+
setCached(address: HexString, entry: StealthRegistryEntry | null): void {
|
|
358
|
+
if (!this.cacheEnabled) return
|
|
359
|
+
|
|
360
|
+
const key = this.getCacheKey(address)
|
|
361
|
+
this.cache.set(key, {
|
|
362
|
+
entry,
|
|
363
|
+
timestamp: Date.now(),
|
|
364
|
+
})
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Clear the cache
|
|
369
|
+
*/
|
|
370
|
+
clearCache(): void {
|
|
371
|
+
this.cache.clear()
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ─── Registration Methods ────────────────────────────────────────────────────
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Build a transaction to register a stealth meta-address
|
|
378
|
+
*
|
|
379
|
+
* @param metaAddress - Meta-address to register
|
|
380
|
+
* @param options - Registration options
|
|
381
|
+
* @returns Transaction to sign and submit
|
|
382
|
+
*/
|
|
383
|
+
buildRegisterTransaction(
|
|
384
|
+
metaAddress: EthereumStealthMetaAddress | string,
|
|
385
|
+
options: RegistryRegisterOptions = {}
|
|
386
|
+
): RegistryTransaction {
|
|
387
|
+
const parsed = typeof metaAddress === 'string'
|
|
388
|
+
? parseEthereumStealthMetaAddress(metaAddress)
|
|
389
|
+
: metaAddress
|
|
390
|
+
|
|
391
|
+
const schemeId = options.schemeId ?? SECP256K1_SCHEME_ID
|
|
392
|
+
|
|
393
|
+
// Encode the meta-address bytes
|
|
394
|
+
const metaAddressBytes = this.encodeMetaAddressBytes(parsed)
|
|
395
|
+
|
|
396
|
+
// Encode: registerKeys(uint256 schemeId, bytes stealthMetaAddress)
|
|
397
|
+
const schemeIdParam = schemeId.toString(16).padStart(64, '0')
|
|
398
|
+
|
|
399
|
+
// ABI encode bytes: offset + length + data
|
|
400
|
+
const offset = (64).toString(16).padStart(64, '0') // 0x40 = 64
|
|
401
|
+
const length = (66).toString(16).padStart(64, '0') // 66 bytes
|
|
402
|
+
const paddedBytes = metaAddressBytes.padEnd(128, '0') // Pad to 64 bytes (2 words)
|
|
403
|
+
|
|
404
|
+
const data = `${REGISTRY_SELECTORS.registerKeys}${schemeIdParam}${offset}${length}${paddedBytes}` as HexString
|
|
405
|
+
|
|
406
|
+
return {
|
|
407
|
+
to: this.registryAddress,
|
|
408
|
+
data,
|
|
409
|
+
value: 0n,
|
|
410
|
+
gasLimit: options.gasLimit ?? 150000n,
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Build a transaction to update an existing registration
|
|
416
|
+
*
|
|
417
|
+
* (Same as register - the contract handles updates)
|
|
418
|
+
*
|
|
419
|
+
* @param metaAddress - New meta-address
|
|
420
|
+
* @param options - Registration options
|
|
421
|
+
* @returns Transaction to sign and submit
|
|
422
|
+
*/
|
|
423
|
+
buildUpdateTransaction(
|
|
424
|
+
metaAddress: EthereumStealthMetaAddress | string,
|
|
425
|
+
options: RegistryRegisterOptions = {}
|
|
426
|
+
): RegistryTransaction {
|
|
427
|
+
return this.buildRegisterTransaction(metaAddress, {
|
|
428
|
+
...options,
|
|
429
|
+
gasLimit: options.gasLimit ?? 100000n, // Lower gas for updates
|
|
430
|
+
})
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ─── Nonce Methods ───────────────────────────────────────────────────────────
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Build call data for getting the nonce of an address
|
|
437
|
+
*
|
|
438
|
+
* Used for signature-based registration on behalf of others.
|
|
439
|
+
*
|
|
440
|
+
* @param address - Address to get nonce for
|
|
441
|
+
* @returns Call data for eth_call
|
|
442
|
+
*/
|
|
443
|
+
buildNonceCallData(address: HexString): { to: HexString; data: HexString } {
|
|
444
|
+
if (!isValidEthAddress(address)) {
|
|
445
|
+
throw new Error(`Invalid Ethereum address: ${address}`)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const addressParam = address.slice(2).padStart(64, '0')
|
|
449
|
+
const data = `${REGISTRY_SELECTORS.nonceOf}${addressParam}` as HexString
|
|
450
|
+
|
|
451
|
+
return {
|
|
452
|
+
to: this.registryAddress,
|
|
453
|
+
data,
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Parse nonce response
|
|
459
|
+
*
|
|
460
|
+
* @param response - Raw response from eth_call
|
|
461
|
+
* @returns Nonce value
|
|
462
|
+
*/
|
|
463
|
+
parseNonceResponse(response: HexString): bigint {
|
|
464
|
+
return BigInt(response)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ─── Utility Methods ─────────────────────────────────────────────────────────
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Get the registry contract address
|
|
471
|
+
*/
|
|
472
|
+
getRegistryAddress(): HexString {
|
|
473
|
+
return this.registryAddress
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Get the network
|
|
478
|
+
*/
|
|
479
|
+
getNetwork(): EthereumNetwork {
|
|
480
|
+
return this.network
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Check if caching is enabled
|
|
485
|
+
*/
|
|
486
|
+
isCacheEnabled(): boolean {
|
|
487
|
+
return this.cacheEnabled
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Enable or disable caching
|
|
492
|
+
*/
|
|
493
|
+
setCacheEnabled(enabled: boolean): void {
|
|
494
|
+
this.cacheEnabled = enabled
|
|
495
|
+
if (!enabled) {
|
|
496
|
+
this.clearCache()
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Get cache key for an address
|
|
502
|
+
*/
|
|
503
|
+
private getCacheKey(address: HexString): string {
|
|
504
|
+
return `${this.network}:${address.toLowerCase()}`
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Encode meta-address to bytes (spending + viewing keys)
|
|
509
|
+
*/
|
|
510
|
+
private encodeMetaAddressBytes(metaAddress: EthereumStealthMetaAddress): string {
|
|
511
|
+
// Remove 0x prefixes and concatenate
|
|
512
|
+
const spending = metaAddress.spendingKey.slice(2)
|
|
513
|
+
const viewing = metaAddress.viewingKey.slice(2)
|
|
514
|
+
return `${spending}${viewing}`
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// ─── Factory Functions ────────────────────────────────────────────────────────
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Create a registry client for a specific network
|
|
522
|
+
*
|
|
523
|
+
* @param network - Target network
|
|
524
|
+
* @param options - Client options
|
|
525
|
+
* @returns Registry client
|
|
526
|
+
*/
|
|
527
|
+
export function createRegistryClient(
|
|
528
|
+
network: EthereumNetwork = 'mainnet',
|
|
529
|
+
options?: {
|
|
530
|
+
registryAddress?: HexString
|
|
531
|
+
enableCache?: boolean
|
|
532
|
+
}
|
|
533
|
+
): RegistryClient {
|
|
534
|
+
return new RegistryClient(network, options)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Create a mainnet registry client
|
|
539
|
+
*/
|
|
540
|
+
export function createMainnetRegistryClient(): RegistryClient {
|
|
541
|
+
return new RegistryClient('mainnet')
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Create a Sepolia testnet registry client
|
|
546
|
+
*/
|
|
547
|
+
export function createSepoliaRegistryClient(): RegistryClient {
|
|
548
|
+
return new RegistryClient('sepolia')
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// ─── Helper Functions ────────────────────────────────────────────────────────
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Check if an address has a registered meta-address
|
|
555
|
+
*
|
|
556
|
+
* Helper that takes raw eth_call response.
|
|
557
|
+
*
|
|
558
|
+
* @param response - eth_call response
|
|
559
|
+
* @returns True if registered
|
|
560
|
+
*/
|
|
561
|
+
export function isRegistered(response: HexString): boolean {
|
|
562
|
+
const data = response.slice(2)
|
|
563
|
+
if (!data || data === '0' || /^0+$/.test(data)) {
|
|
564
|
+
return false
|
|
565
|
+
}
|
|
566
|
+
// Check if length is non-zero
|
|
567
|
+
if (data.length >= 128) {
|
|
568
|
+
const lengthHex = data.slice(64, 128)
|
|
569
|
+
const length = parseInt(lengthHex, 16)
|
|
570
|
+
return length > 0
|
|
571
|
+
}
|
|
572
|
+
return false
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Extract scheme ID from meta-address prefix
|
|
577
|
+
*
|
|
578
|
+
* @param _metaAddress - Meta-address bytes or encoded string (unused, for future expansion)
|
|
579
|
+
* @returns Scheme ID
|
|
580
|
+
*/
|
|
581
|
+
export function extractSchemeId(_metaAddress: HexString | string): number {
|
|
582
|
+
// For now, we only support secp256k1
|
|
583
|
+
return SECP256K1_SCHEME_ID
|
|
584
|
+
}
|