@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
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
getAssociatedTokenAddress,
|
|
14
14
|
createTransferInstruction,
|
|
15
15
|
getAccount,
|
|
16
|
-
TOKEN_PROGRAM_ID,
|
|
17
16
|
} from '@solana/spl-token'
|
|
18
17
|
import {
|
|
19
18
|
checkEd25519StealthAddress,
|
|
@@ -32,10 +31,14 @@ import {
|
|
|
32
31
|
SIP_MEMO_PREFIX,
|
|
33
32
|
MEMO_PROGRAM_ID,
|
|
34
33
|
getExplorerUrl,
|
|
35
|
-
|
|
34
|
+
DEFAULT_SCAN_LIMIT,
|
|
35
|
+
VIEW_TAG_MAX,
|
|
36
36
|
type SolanaCluster,
|
|
37
37
|
} from './constants'
|
|
38
|
-
import {
|
|
38
|
+
import { getTokenSymbol, parseTokenTransferFromBalances } from './utils'
|
|
39
|
+
import type { SolanaRPCProvider } from './providers/interface'
|
|
40
|
+
import { hexToBytes } from '@noble/hashes/utils'
|
|
41
|
+
import { ed25519 } from '@noble/curves/ed25519'
|
|
39
42
|
|
|
40
43
|
/**
|
|
41
44
|
* Scan for incoming stealth payments
|
|
@@ -69,7 +72,8 @@ export async function scanForPayments(
|
|
|
69
72
|
spendingPublicKey,
|
|
70
73
|
fromSlot,
|
|
71
74
|
toSlot,
|
|
72
|
-
limit =
|
|
75
|
+
limit = DEFAULT_SCAN_LIMIT,
|
|
76
|
+
provider,
|
|
73
77
|
} = params
|
|
74
78
|
|
|
75
79
|
const results: SolanaScanResult[] = []
|
|
@@ -117,39 +121,88 @@ export async function scanForPayments(
|
|
|
117
121
|
const announcement = parseAnnouncement(memoContent)
|
|
118
122
|
if (!announcement) continue
|
|
119
123
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
// M5 FIX: Wrap ephemeral key conversion in try-catch
|
|
125
|
+
let ephemeralPubKeyHex: HexString
|
|
126
|
+
try {
|
|
127
|
+
ephemeralPubKeyHex = solanaAddressToEd25519PublicKey(
|
|
128
|
+
announcement.ephemeralPublicKey
|
|
129
|
+
)
|
|
130
|
+
} catch {
|
|
131
|
+
// Invalid ephemeral key format, skip this announcement
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
124
134
|
|
|
125
135
|
// Construct stealth address object for checking
|
|
126
136
|
// viewTag is a number (0-255), parse from hex string
|
|
127
137
|
const viewTagNumber = parseInt(announcement.viewTag, 16)
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
|
|
139
|
+
// M5 FIX: Validate view tag range
|
|
140
|
+
if (!Number.isInteger(viewTagNumber) || viewTagNumber < 0 || viewTagNumber > VIEW_TAG_MAX) {
|
|
141
|
+
continue
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let stealthAddressHex: HexString
|
|
145
|
+
try {
|
|
146
|
+
stealthAddressHex = announcement.stealthAddress
|
|
130
147
|
? solanaAddressToEd25519PublicKey(announcement.stealthAddress)
|
|
131
|
-
: ('0x' + '00'.repeat(32)) as HexString
|
|
148
|
+
: ('0x' + '00'.repeat(32)) as HexString
|
|
149
|
+
} catch {
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const stealthAddressToCheck: StealthAddress = {
|
|
154
|
+
address: stealthAddressHex,
|
|
132
155
|
ephemeralPublicKey: ephemeralPubKeyHex,
|
|
133
156
|
viewTag: viewTagNumber,
|
|
134
157
|
}
|
|
135
158
|
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
159
|
+
// M5 FIX: Wrap checkEd25519StealthAddress in try-catch
|
|
160
|
+
// This can throw for invalid curve points
|
|
161
|
+
let isOurs = false
|
|
162
|
+
try {
|
|
163
|
+
isOurs = checkEd25519StealthAddress(
|
|
164
|
+
stealthAddressToCheck,
|
|
165
|
+
viewingPrivateKey,
|
|
166
|
+
spendingPublicKey
|
|
167
|
+
)
|
|
168
|
+
} catch {
|
|
169
|
+
// Invalid keys or malformed data - not our payment
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
142
172
|
|
|
143
173
|
if (isOurs) {
|
|
144
|
-
// Parse token transfer from transaction
|
|
145
|
-
const transferInfo =
|
|
174
|
+
// Parse token transfer from transaction using shared utility
|
|
175
|
+
const transferInfo = parseTokenTransferFromBalances(
|
|
176
|
+
tx?.meta?.preTokenBalances as Parameters<typeof parseTokenTransferFromBalances>[0],
|
|
177
|
+
tx?.meta?.postTokenBalances as Parameters<typeof parseTokenTransferFromBalances>[1]
|
|
178
|
+
)
|
|
146
179
|
if (transferInfo) {
|
|
180
|
+
// If provider is available, use it for more accurate current balance
|
|
181
|
+
let amount = transferInfo.amount
|
|
182
|
+
const tokenSymbol = getTokenSymbol(transferInfo.mint)
|
|
183
|
+
|
|
184
|
+
if (provider && announcement.stealthAddress) {
|
|
185
|
+
try {
|
|
186
|
+
// Use getTokenBalance for efficient single-token query
|
|
187
|
+
const balance = await provider.getTokenBalance(
|
|
188
|
+
announcement.stealthAddress,
|
|
189
|
+
transferInfo.mint
|
|
190
|
+
)
|
|
191
|
+
// Only use provider balance if > 0 (confirms tokens still there)
|
|
192
|
+
if (balance > 0n) {
|
|
193
|
+
amount = balance
|
|
194
|
+
}
|
|
195
|
+
} catch {
|
|
196
|
+
// Fallback to parsed transfer info if provider fails
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
147
200
|
results.push({
|
|
148
201
|
stealthAddress: announcement.stealthAddress || '',
|
|
149
202
|
ephemeralPublicKey: announcement.ephemeralPublicKey,
|
|
150
|
-
amount
|
|
203
|
+
amount,
|
|
151
204
|
mint: transferInfo.mint,
|
|
152
|
-
tokenSymbol
|
|
205
|
+
tokenSymbol,
|
|
153
206
|
txSignature: sigInfo.signature,
|
|
154
207
|
slot: sigInfo.slot,
|
|
155
208
|
timestamp: sigInfo.blockTime || 0,
|
|
@@ -157,14 +210,15 @@ export async function scanForPayments(
|
|
|
157
210
|
}
|
|
158
211
|
}
|
|
159
212
|
}
|
|
160
|
-
} catch
|
|
161
|
-
// Skip failed transaction parsing
|
|
162
|
-
|
|
213
|
+
} catch {
|
|
214
|
+
// M10 FIX: Skip failed transaction parsing silently
|
|
215
|
+
// Individual tx parse failures shouldn't block scanning
|
|
163
216
|
}
|
|
164
217
|
}
|
|
165
218
|
} catch (err) {
|
|
166
|
-
console.error
|
|
167
|
-
|
|
219
|
+
// M10 FIX: Remove console.error, throw proper error
|
|
220
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
221
|
+
throw new Error(`Failed to scan for payments: ${message}`)
|
|
168
222
|
}
|
|
169
223
|
|
|
170
224
|
return results
|
|
@@ -193,6 +247,9 @@ export async function scanForPayments(
|
|
|
193
247
|
* console.log('Claimed! Tx:', result.txSignature)
|
|
194
248
|
* ```
|
|
195
249
|
*/
|
|
250
|
+
/** Minimum SOL balance required for transaction fees (in lamports) */
|
|
251
|
+
const MIN_SOL_FOR_FEES = 5000n // ~0.000005 SOL, typical tx fee
|
|
252
|
+
|
|
196
253
|
export async function claimStealthPayment(
|
|
197
254
|
params: SolanaClaimParams
|
|
198
255
|
): Promise<SolanaClaimResult> {
|
|
@@ -206,6 +263,17 @@ export async function claimStealthPayment(
|
|
|
206
263
|
mint,
|
|
207
264
|
} = params
|
|
208
265
|
|
|
266
|
+
// M7 FIX: Check SOL balance for fees before attempting claim
|
|
267
|
+
const stealthPubkeyForBalance = new PublicKey(stealthAddress)
|
|
268
|
+
const solBalance = await connection.getBalance(stealthPubkeyForBalance)
|
|
269
|
+
if (BigInt(solBalance) < MIN_SOL_FOR_FEES) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`Insufficient SOL for transaction fees. Stealth address has ${solBalance} lamports, ` +
|
|
272
|
+
`needs at least ${MIN_SOL_FOR_FEES} lamports (~0.000005 SOL). ` +
|
|
273
|
+
`Fund the stealth address with SOL before claiming.`
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
209
277
|
// Convert addresses to hex for SDK functions
|
|
210
278
|
const stealthAddressHex = solanaAddressToEd25519PublicKey(stealthAddress)
|
|
211
279
|
const ephemeralPubKeyHex = solanaAddressToEd25519PublicKey(ephemeralPublicKey)
|
|
@@ -229,11 +297,31 @@ export async function claimStealthPayment(
|
|
|
229
297
|
// The SDK returns a scalar, so we need to handle this carefully
|
|
230
298
|
const stealthPrivKeyBytes = hexToBytes(recovery.privateKey.slice(2))
|
|
231
299
|
|
|
232
|
-
//
|
|
233
|
-
//
|
|
300
|
+
// Validate that the derived private key (scalar) produces the expected public key
|
|
301
|
+
// Note: SIP derives a scalar, not a seed. We use scalar multiplication to verify.
|
|
234
302
|
const stealthPubkey = new PublicKey(stealthAddress)
|
|
303
|
+
const expectedPubKeyBytes = stealthPubkey.toBytes()
|
|
304
|
+
|
|
305
|
+
// Convert scalar bytes to bigint (little-endian for ed25519)
|
|
306
|
+
const scalarBigInt = bytesToBigIntLE(stealthPrivKeyBytes)
|
|
307
|
+
const ED25519_ORDER = 2n ** 252n + 27742317777372353535851937790883648493n
|
|
308
|
+
let validScalar = scalarBigInt % ED25519_ORDER
|
|
309
|
+
if (validScalar === 0n) validScalar = 1n
|
|
310
|
+
|
|
311
|
+
// Derive public key via scalar multiplication
|
|
312
|
+
const derivedPubKeyBytes = ed25519.ExtendedPoint.BASE.multiply(validScalar).toRawBytes()
|
|
313
|
+
|
|
314
|
+
if (!derivedPubKeyBytes.every((b, i) => b === expectedPubKeyBytes[i])) {
|
|
315
|
+
throw new Error(
|
|
316
|
+
'Stealth key derivation failed: derived private key does not produce expected public key. ' +
|
|
317
|
+
'This may indicate incorrect spending/viewing keys or corrupted announcement data.'
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Solana keypairs expect 64 bytes (32 byte seed + 32 byte public key)
|
|
322
|
+
// We construct this from the derived scalar (now validated)
|
|
235
323
|
const stealthKeypair = Keypair.fromSecretKey(
|
|
236
|
-
new Uint8Array([...stealthPrivKeyBytes, ...
|
|
324
|
+
new Uint8Array([...stealthPrivKeyBytes, ...expectedPubKeyBytes])
|
|
237
325
|
)
|
|
238
326
|
|
|
239
327
|
// Get token accounts
|
|
@@ -306,12 +394,39 @@ export async function claimStealthPayment(
|
|
|
306
394
|
|
|
307
395
|
/**
|
|
308
396
|
* Get token balance for a stealth address
|
|
397
|
+
*
|
|
398
|
+
* @param connection - Solana RPC connection
|
|
399
|
+
* @param stealthAddress - Stealth address to check (base58)
|
|
400
|
+
* @param mint - SPL token mint address
|
|
401
|
+
* @param provider - Optional RPC provider for efficient queries
|
|
402
|
+
* @returns Token balance in smallest unit
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```typescript
|
|
406
|
+
* // Using standard RPC
|
|
407
|
+
* const balance = await getStealthBalance(connection, stealthAddr, mint)
|
|
408
|
+
*
|
|
409
|
+
* // Using Helius for efficient queries
|
|
410
|
+
* const helius = createProvider('helius', { apiKey })
|
|
411
|
+
* const balance = await getStealthBalance(connection, stealthAddr, mint, helius)
|
|
412
|
+
* ```
|
|
309
413
|
*/
|
|
310
414
|
export async function getStealthBalance(
|
|
311
415
|
connection: SolanaScanParams['connection'],
|
|
312
416
|
stealthAddress: string,
|
|
313
|
-
mint: PublicKey
|
|
417
|
+
mint: PublicKey,
|
|
418
|
+
provider?: SolanaRPCProvider
|
|
314
419
|
): Promise<bigint> {
|
|
420
|
+
// Use provider if available for efficient queries
|
|
421
|
+
if (provider) {
|
|
422
|
+
try {
|
|
423
|
+
return await provider.getTokenBalance(stealthAddress, mint.toBase58())
|
|
424
|
+
} catch {
|
|
425
|
+
// Fallback to standard RPC if provider fails
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Standard RPC fallback
|
|
315
430
|
try {
|
|
316
431
|
const stealthPubkey = new PublicKey(stealthAddress)
|
|
317
432
|
const ata = await getAssociatedTokenAddress(mint, stealthPubkey, true)
|
|
@@ -322,51 +437,16 @@ export async function getStealthBalance(
|
|
|
322
437
|
}
|
|
323
438
|
}
|
|
324
439
|
|
|
325
|
-
|
|
326
|
-
* Parse token transfer info from a transaction
|
|
327
|
-
*/
|
|
328
|
-
function parseTokenTransfer(
|
|
329
|
-
tx: Awaited<ReturnType<typeof import('@solana/web3.js').Connection.prototype.getTransaction>>
|
|
330
|
-
): { mint: string; amount: bigint } | null {
|
|
331
|
-
if (!tx?.meta?.postTokenBalances || !tx.meta.preTokenBalances) {
|
|
332
|
-
return null
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Find token balance changes
|
|
336
|
-
for (let i = 0; i < tx.meta.postTokenBalances.length; i++) {
|
|
337
|
-
const post = tx.meta.postTokenBalances[i]
|
|
338
|
-
const pre = tx.meta.preTokenBalances.find(
|
|
339
|
-
(p) => p.accountIndex === post.accountIndex
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
const postAmount = BigInt(post.uiTokenAmount.amount)
|
|
343
|
-
const preAmount = pre ? BigInt(pre.uiTokenAmount.amount) : 0n
|
|
344
|
-
|
|
345
|
-
if (postAmount > preAmount) {
|
|
346
|
-
return {
|
|
347
|
-
mint: post.mint,
|
|
348
|
-
amount: postAmount - preAmount,
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return null
|
|
354
|
-
}
|
|
440
|
+
// Token transfer parsing and symbol lookup moved to ./utils.ts (L3 fix)
|
|
355
441
|
|
|
356
442
|
/**
|
|
357
|
-
*
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
return undefined
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Detect Solana cluster from RPC endpoint
|
|
443
|
+
* Detect Solana cluster from RPC endpoint URL
|
|
444
|
+
*
|
|
445
|
+
* Parses the endpoint URL to determine which Solana cluster it connects to.
|
|
446
|
+
*
|
|
447
|
+
* @param endpoint - RPC endpoint URL
|
|
448
|
+
* @returns Detected cluster name
|
|
449
|
+
* @internal
|
|
370
450
|
*/
|
|
371
451
|
function detectCluster(endpoint: string): SolanaCluster {
|
|
372
452
|
if (endpoint.includes('devnet')) {
|
|
@@ -380,3 +460,20 @@ function detectCluster(endpoint: string): SolanaCluster {
|
|
|
380
460
|
}
|
|
381
461
|
return 'mainnet-beta'
|
|
382
462
|
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Convert bytes to bigint in little-endian format
|
|
466
|
+
*
|
|
467
|
+
* Used for ed25519 scalar conversion where bytes are in little-endian order.
|
|
468
|
+
*
|
|
469
|
+
* @param bytes - Byte array to convert
|
|
470
|
+
* @returns BigInt representation of the bytes
|
|
471
|
+
* @internal
|
|
472
|
+
*/
|
|
473
|
+
function bytesToBigIntLE(bytes: Uint8Array): bigint {
|
|
474
|
+
let result = 0n
|
|
475
|
+
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
476
|
+
result = (result << 8n) | BigInt(bytes[i])
|
|
477
|
+
}
|
|
478
|
+
return result
|
|
479
|
+
}
|