@sip-protocol/sdk 0.7.3 → 0.8.0
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/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 +44 -11
- 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
|
@@ -9,9 +9,8 @@ import {
|
|
|
9
9
|
PublicKey,
|
|
10
10
|
Transaction,
|
|
11
11
|
TransactionInstruction,
|
|
12
|
-
SystemProgram,
|
|
13
|
-
LAMPORTS_PER_SOL,
|
|
14
12
|
} from '@solana/web3.js'
|
|
13
|
+
import { ValidationError } from '../../errors'
|
|
15
14
|
import {
|
|
16
15
|
getAssociatedTokenAddress,
|
|
17
16
|
createAssociatedTokenAccountInstruction,
|
|
@@ -75,6 +74,11 @@ import { bytesToHex } from '@noble/hashes/utils'
|
|
|
75
74
|
export async function sendPrivateSPLTransfer(
|
|
76
75
|
params: SolanaPrivateTransferParams
|
|
77
76
|
): Promise<SolanaPrivateTransferResult> {
|
|
77
|
+
// H-6 FIX: Comprehensive input validation
|
|
78
|
+
if (!params) {
|
|
79
|
+
throw new ValidationError('params is required', 'params')
|
|
80
|
+
}
|
|
81
|
+
|
|
78
82
|
const {
|
|
79
83
|
connection,
|
|
80
84
|
sender,
|
|
@@ -85,10 +89,75 @@ export async function sendPrivateSPLTransfer(
|
|
|
85
89
|
signTransaction,
|
|
86
90
|
} = params
|
|
87
91
|
|
|
88
|
-
// Validate
|
|
92
|
+
// Validate connection
|
|
93
|
+
if (!connection) {
|
|
94
|
+
throw new ValidationError('connection is required', 'connection')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Validate sender
|
|
98
|
+
if (!sender) {
|
|
99
|
+
throw new ValidationError('sender is required', 'sender')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Validate senderTokenAccount
|
|
103
|
+
if (!senderTokenAccount) {
|
|
104
|
+
throw new ValidationError('senderTokenAccount is required', 'senderTokenAccount')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Validate mint
|
|
108
|
+
if (!mint) {
|
|
109
|
+
throw new ValidationError('mint is required', 'mint')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Validate signTransaction callback
|
|
113
|
+
if (typeof signTransaction !== 'function') {
|
|
114
|
+
throw new ValidationError('signTransaction must be a function', 'signTransaction')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Validate amount
|
|
118
|
+
if (amount === undefined || amount === null) {
|
|
119
|
+
throw new ValidationError('amount is required', 'amount')
|
|
120
|
+
}
|
|
121
|
+
if (typeof amount !== 'bigint') {
|
|
122
|
+
throw new ValidationError('amount must be a bigint', 'amount')
|
|
123
|
+
}
|
|
124
|
+
if (amount <= 0n) {
|
|
125
|
+
throw new ValidationError('amount must be greater than 0', 'amount')
|
|
126
|
+
}
|
|
127
|
+
// Prevent unreasonably large amounts (> 2^64, which is the max for SPL tokens)
|
|
128
|
+
const MAX_SPL_AMOUNT = 2n ** 64n - 1n
|
|
129
|
+
if (amount > MAX_SPL_AMOUNT) {
|
|
130
|
+
throw new ValidationError(`amount exceeds maximum SPL token amount`, 'amount')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate recipient meta-address
|
|
134
|
+
if (!recipientMetaAddress) {
|
|
135
|
+
throw new ValidationError('recipientMetaAddress is required', 'recipientMetaAddress')
|
|
136
|
+
}
|
|
89
137
|
if (recipientMetaAddress.chain !== 'solana') {
|
|
90
|
-
throw new
|
|
91
|
-
`Invalid chain: expected 'solana', got '${recipientMetaAddress.chain}'
|
|
138
|
+
throw new ValidationError(
|
|
139
|
+
`Invalid chain: expected 'solana', got '${recipientMetaAddress.chain}'`,
|
|
140
|
+
'recipientMetaAddress.chain'
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
// Validate meta-address keys are present
|
|
144
|
+
if (!recipientMetaAddress.spendingKey) {
|
|
145
|
+
throw new ValidationError('recipientMetaAddress.spendingKey is required', 'recipientMetaAddress.spendingKey')
|
|
146
|
+
}
|
|
147
|
+
if (!recipientMetaAddress.viewingKey) {
|
|
148
|
+
throw new ValidationError('recipientMetaAddress.viewingKey is required', 'recipientMetaAddress.viewingKey')
|
|
149
|
+
}
|
|
150
|
+
// Validate key format (should be hex strings starting with 0x)
|
|
151
|
+
if (!recipientMetaAddress.spendingKey.startsWith('0x') || recipientMetaAddress.spendingKey.length !== 66) {
|
|
152
|
+
throw new ValidationError(
|
|
153
|
+
'recipientMetaAddress.spendingKey must be a 32-byte hex string (0x + 64 chars)',
|
|
154
|
+
'recipientMetaAddress.spendingKey'
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
if (!recipientMetaAddress.viewingKey.startsWith('0x') || recipientMetaAddress.viewingKey.length !== 66) {
|
|
158
|
+
throw new ValidationError(
|
|
159
|
+
'recipientMetaAddress.viewingKey must be a 32-byte hex string (0x + 64 chars)',
|
|
160
|
+
'recipientMetaAddress.viewingKey'
|
|
92
161
|
)
|
|
93
162
|
}
|
|
94
163
|
|
|
@@ -49,11 +49,19 @@ export interface SolanaPrivateTransferResult {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Parameters for scanning for incoming stealth payments
|
|
52
|
+
*
|
|
53
|
+
* @security This interface requires sensitive cryptographic keys.
|
|
54
|
+
* Never log, store in plain text, or transmit these keys insecurely.
|
|
52
55
|
*/
|
|
53
56
|
export interface SolanaScanParams {
|
|
54
57
|
/** Solana RPC connection */
|
|
55
58
|
connection: Connection
|
|
56
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Recipient's viewing private key (hex)
|
|
61
|
+
*
|
|
62
|
+
* @security SENSITIVE - This key enables scanning for incoming payments.
|
|
63
|
+
* Store securely (encrypted). Never log or expose in error messages.
|
|
64
|
+
*/
|
|
57
65
|
viewingPrivateKey: HexString
|
|
58
66
|
/** Recipient's spending public key (hex) */
|
|
59
67
|
spendingPublicKey: HexString
|
|
@@ -107,6 +115,10 @@ export interface SolanaScanResult {
|
|
|
107
115
|
|
|
108
116
|
/**
|
|
109
117
|
* Parameters for claiming a stealth payment
|
|
118
|
+
*
|
|
119
|
+
* @security This interface requires highly sensitive cryptographic keys.
|
|
120
|
+
* The spending private key can authorize fund transfers.
|
|
121
|
+
* Never log, store in plain text, or transmit these keys insecurely.
|
|
110
122
|
*/
|
|
111
123
|
export interface SolanaClaimParams {
|
|
112
124
|
/** Solana RPC connection */
|
|
@@ -115,9 +127,21 @@ export interface SolanaClaimParams {
|
|
|
115
127
|
stealthAddress: string
|
|
116
128
|
/** Ephemeral public key from the payment (base58) */
|
|
117
129
|
ephemeralPublicKey: string
|
|
118
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Recipient's viewing private key (hex)
|
|
132
|
+
*
|
|
133
|
+
* @security SENSITIVE - Required for stealth key derivation.
|
|
134
|
+
* Store securely (encrypted). Never log or expose in error messages.
|
|
135
|
+
*/
|
|
119
136
|
viewingPrivateKey: HexString
|
|
120
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Recipient's spending private key (hex)
|
|
139
|
+
*
|
|
140
|
+
* @security CRITICAL - This key can authorize fund transfers.
|
|
141
|
+
* Store with maximum security (hardware wallet, secure enclave, or encrypted storage).
|
|
142
|
+
* Never log, expose in errors, or transmit over network.
|
|
143
|
+
* Clear from memory after use when possible.
|
|
144
|
+
*/
|
|
121
145
|
spendingPrivateKey: HexString
|
|
122
146
|
/** Destination address to send claimed funds (base58) */
|
|
123
147
|
destinationAddress: string
|
|
@@ -154,6 +178,8 @@ export interface SolanaAnnouncement {
|
|
|
154
178
|
/**
|
|
155
179
|
* Parse announcement from memo string
|
|
156
180
|
* Format: SIP:1:<ephemeral_pubkey_base58>:<view_tag_hex>
|
|
181
|
+
*
|
|
182
|
+
* M4 FIX: Validates view tag is exactly 1-2 hex characters (1 byte)
|
|
157
183
|
*/
|
|
158
184
|
export function parseAnnouncement(memo: string): SolanaAnnouncement | null {
|
|
159
185
|
if (!memo.startsWith('SIP:1:')) {
|
|
@@ -165,10 +191,35 @@ export function parseAnnouncement(memo: string): SolanaAnnouncement | null {
|
|
|
165
191
|
return null
|
|
166
192
|
}
|
|
167
193
|
|
|
194
|
+
const ephemeralPublicKey = parts[0]
|
|
195
|
+
const viewTag = parts[1]
|
|
196
|
+
const stealthAddress = parts[2]
|
|
197
|
+
|
|
198
|
+
// M4 FIX: Validate ephemeral public key (base58, 32-44 chars for Solana)
|
|
199
|
+
if (!ephemeralPublicKey || ephemeralPublicKey.length < 32 || ephemeralPublicKey.length > 44) {
|
|
200
|
+
return null
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// M4 FIX: Validate view tag is 1-2 hex characters (represents 1 byte: 0-255)
|
|
204
|
+
if (!viewTag || viewTag.length > 2 || !/^[0-9a-fA-F]+$/.test(viewTag)) {
|
|
205
|
+
return null
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// M4 FIX: Validate view tag numeric range (0-255)
|
|
209
|
+
const viewTagNum = parseInt(viewTag, 16)
|
|
210
|
+
if (viewTagNum < 0 || viewTagNum > 255) {
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// M4 FIX: Validate stealth address if provided
|
|
215
|
+
if (stealthAddress && (stealthAddress.length < 32 || stealthAddress.length > 44)) {
|
|
216
|
+
return null
|
|
217
|
+
}
|
|
218
|
+
|
|
168
219
|
return {
|
|
169
|
-
ephemeralPublicKey
|
|
170
|
-
viewTag
|
|
171
|
-
stealthAddress
|
|
220
|
+
ephemeralPublicKey,
|
|
221
|
+
viewTag,
|
|
222
|
+
stealthAddress,
|
|
172
223
|
}
|
|
173
224
|
}
|
|
174
225
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana Shared Utilities
|
|
3
|
+
*
|
|
4
|
+
* Common utility functions used across scan.ts and webhook.ts.
|
|
5
|
+
* Extracted to reduce code duplication (L3 audit fix).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { SOLANA_TOKEN_MINTS } from './constants'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Token balance entry from Solana transaction metadata
|
|
12
|
+
*
|
|
13
|
+
* Common interface for pre/post token balances used in both
|
|
14
|
+
* standard RPC and webhook transaction parsing.
|
|
15
|
+
*/
|
|
16
|
+
export interface TokenBalanceEntry {
|
|
17
|
+
accountIndex: number
|
|
18
|
+
mint: string
|
|
19
|
+
uiTokenAmount: {
|
|
20
|
+
amount: string
|
|
21
|
+
decimals: number
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Result of parsing a token transfer from transaction balances
|
|
27
|
+
*/
|
|
28
|
+
export interface TokenTransferInfo {
|
|
29
|
+
/** Token mint address (base58) */
|
|
30
|
+
mint: string
|
|
31
|
+
/** Transfer amount in smallest unit */
|
|
32
|
+
amount: bigint
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get token symbol from mint address
|
|
37
|
+
*
|
|
38
|
+
* Looks up the token symbol for a known mint address in our registry.
|
|
39
|
+
* Returns undefined for unknown tokens.
|
|
40
|
+
*
|
|
41
|
+
* @param mint - SPL token mint address (base58)
|
|
42
|
+
* @returns Token symbol (e.g., 'USDC') or undefined if not found
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* getTokenSymbol('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')
|
|
47
|
+
* // => 'USDC'
|
|
48
|
+
*
|
|
49
|
+
* getTokenSymbol('unknown-mint-address')
|
|
50
|
+
* // => undefined
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function getTokenSymbol(mint: string): string | undefined {
|
|
54
|
+
for (const [symbol, address] of Object.entries(SOLANA_TOKEN_MINTS)) {
|
|
55
|
+
if (address === mint) {
|
|
56
|
+
return symbol
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return undefined
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Parse token transfer info from pre/post balance changes
|
|
64
|
+
*
|
|
65
|
+
* Analyzes pre and post token balances to determine the transferred
|
|
66
|
+
* token and amount. Finds the first account with an increased balance.
|
|
67
|
+
*
|
|
68
|
+
* @param preBalances - Pre-transaction token balances
|
|
69
|
+
* @param postBalances - Post-transaction token balances
|
|
70
|
+
* @returns Token mint and amount transferred, or null if no transfer found
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const transfer = parseTokenTransferFromBalances(
|
|
75
|
+
* tx.meta.preTokenBalances,
|
|
76
|
+
* tx.meta.postTokenBalances
|
|
77
|
+
* )
|
|
78
|
+
*
|
|
79
|
+
* if (transfer) {
|
|
80
|
+
* console.log(`Received ${transfer.amount} of ${transfer.mint}`)
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function parseTokenTransferFromBalances(
|
|
85
|
+
preBalances: TokenBalanceEntry[] | undefined | null,
|
|
86
|
+
postBalances: TokenBalanceEntry[] | undefined | null
|
|
87
|
+
): TokenTransferInfo | null {
|
|
88
|
+
if (!postBalances || !preBalances) {
|
|
89
|
+
return null
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Find token balance changes (account with increased balance)
|
|
93
|
+
for (const post of postBalances) {
|
|
94
|
+
const pre = preBalances.find(
|
|
95
|
+
(p) => p.accountIndex === post.accountIndex
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
const postAmount = BigInt(post.uiTokenAmount.amount)
|
|
99
|
+
const preAmount = pre ? BigInt(pre.uiTokenAmount.amount) : 0n
|
|
100
|
+
|
|
101
|
+
if (postAmount > preAmount) {
|
|
102
|
+
return {
|
|
103
|
+
mint: post.mint,
|
|
104
|
+
amount: postAmount - preAmount,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return null
|
|
110
|
+
}
|