@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.
Files changed (263) hide show
  1. package/README.md +267 -0
  2. package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
  3. package/dist/browser.d.mts +10 -4
  4. package/dist/browser.d.ts +10 -4
  5. package/dist/browser.js +47556 -19603
  6. package/dist/browser.mjs +628 -48
  7. package/dist/chunk-4GRJ5MAW.mjs +152 -0
  8. package/dist/chunk-5D7A3L3W.mjs +717 -0
  9. package/dist/chunk-64AYA5F5.mjs +7834 -0
  10. package/dist/chunk-GMDGB22A.mjs +379 -0
  11. package/dist/chunk-I534WKN7.mjs +328 -0
  12. package/dist/chunk-IBZVA5Y7.mjs +1003 -0
  13. package/dist/chunk-PRRZAWJE.mjs +223 -0
  14. package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
  15. package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
  16. package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
  17. package/dist/constants-LHAAUC2T.mjs +51 -0
  18. package/dist/dist-2OGQ7FED.mjs +3957 -0
  19. package/dist/dist-IFHPYLDX.mjs +254 -0
  20. package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
  21. package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
  22. package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
  23. package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
  24. package/dist/index.d.mts +9 -3
  25. package/dist/index.d.ts +9 -3
  26. package/dist/index.js +48396 -19623
  27. package/dist/index.mjs +537 -19
  28. package/dist/interface-Bf7w1PLW.d.mts +679 -0
  29. package/dist/interface-Bf7w1PLW.d.ts +679 -0
  30. package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
  31. package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
  32. package/dist/proofs/halo2.d.mts +151 -0
  33. package/dist/proofs/halo2.d.ts +151 -0
  34. package/dist/proofs/halo2.js +350 -0
  35. package/dist/proofs/halo2.mjs +11 -0
  36. package/dist/proofs/kimchi.d.mts +160 -0
  37. package/dist/proofs/kimchi.d.ts +160 -0
  38. package/dist/proofs/kimchi.js +431 -0
  39. package/dist/proofs/kimchi.mjs +13 -0
  40. package/dist/proofs/noir.d.mts +1 -1
  41. package/dist/proofs/noir.d.ts +1 -1
  42. package/dist/proofs/noir.js +74 -18
  43. package/dist/proofs/noir.mjs +84 -24
  44. package/dist/solana-U3MEGU7W.mjs +280 -0
  45. package/dist/validity_proof-3POXLPNY.mjs +21 -0
  46. package/package.json +44 -11
  47. package/src/adapters/index.ts +41 -0
  48. package/src/adapters/jupiter.ts +571 -0
  49. package/src/adapters/near-intents.ts +135 -0
  50. package/src/advisor/advisor.ts +653 -0
  51. package/src/advisor/index.ts +54 -0
  52. package/src/advisor/tools.ts +303 -0
  53. package/src/advisor/types.ts +164 -0
  54. package/src/chains/ethereum/announcement.ts +536 -0
  55. package/src/chains/ethereum/bnb-optimizations.ts +474 -0
  56. package/src/chains/ethereum/commitment.ts +522 -0
  57. package/src/chains/ethereum/constants.ts +462 -0
  58. package/src/chains/ethereum/deployment.ts +596 -0
  59. package/src/chains/ethereum/gas-estimation.ts +538 -0
  60. package/src/chains/ethereum/index.ts +268 -0
  61. package/src/chains/ethereum/optimizations.ts +614 -0
  62. package/src/chains/ethereum/privacy-adapter.ts +855 -0
  63. package/src/chains/ethereum/registry.ts +584 -0
  64. package/src/chains/ethereum/rpc.ts +905 -0
  65. package/src/chains/ethereum/stealth.ts +491 -0
  66. package/src/chains/ethereum/token.ts +790 -0
  67. package/src/chains/ethereum/transfer.ts +637 -0
  68. package/src/chains/ethereum/types.ts +456 -0
  69. package/src/chains/ethereum/viewing-key.ts +455 -0
  70. package/src/chains/near/commitment.ts +608 -0
  71. package/src/chains/near/constants.ts +284 -0
  72. package/src/chains/near/function-call.ts +871 -0
  73. package/src/chains/near/history.ts +654 -0
  74. package/src/chains/near/implicit-account.ts +840 -0
  75. package/src/chains/near/index.ts +393 -0
  76. package/src/chains/near/native-transfer.ts +658 -0
  77. package/src/chains/near/nep141.ts +775 -0
  78. package/src/chains/near/privacy-adapter.ts +889 -0
  79. package/src/chains/near/resolver.ts +971 -0
  80. package/src/chains/near/rpc.ts +1016 -0
  81. package/src/chains/near/stealth.ts +419 -0
  82. package/src/chains/near/types.ts +317 -0
  83. package/src/chains/near/viewing-key.ts +876 -0
  84. package/src/chains/solana/anchor-transfer.ts +386 -0
  85. package/src/chains/solana/commitment.ts +577 -0
  86. package/src/chains/solana/constants.ts +126 -12
  87. package/src/chains/solana/ephemeral-keys.ts +543 -0
  88. package/src/chains/solana/index.ts +252 -1
  89. package/src/chains/solana/key-derivation.ts +418 -0
  90. package/src/chains/solana/kit-compat.ts +334 -0
  91. package/src/chains/solana/optimizations.ts +560 -0
  92. package/src/chains/solana/privacy-adapter.ts +605 -0
  93. package/src/chains/solana/providers/generic.ts +47 -6
  94. package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
  95. package/src/chains/solana/providers/helius-enhanced.ts +623 -0
  96. package/src/chains/solana/providers/helius.ts +186 -33
  97. package/src/chains/solana/providers/index.ts +31 -0
  98. package/src/chains/solana/providers/interface.ts +61 -18
  99. package/src/chains/solana/providers/quicknode.ts +409 -0
  100. package/src/chains/solana/providers/triton.ts +426 -0
  101. package/src/chains/solana/providers/webhook.ts +338 -67
  102. package/src/chains/solana/rpc-client.ts +1150 -0
  103. package/src/chains/solana/scan.ts +83 -66
  104. package/src/chains/solana/sol-transfer.ts +732 -0
  105. package/src/chains/solana/spl-transfer.ts +886 -0
  106. package/src/chains/solana/stealth-scanner.ts +703 -0
  107. package/src/chains/solana/sunspot-verifier.ts +453 -0
  108. package/src/chains/solana/transaction-builder.ts +755 -0
  109. package/src/chains/solana/transfer.ts +74 -5
  110. package/src/chains/solana/types.ts +57 -6
  111. package/src/chains/solana/utils.ts +110 -0
  112. package/src/chains/solana/viewing-key.ts +807 -0
  113. package/src/compliance/fireblocks.ts +921 -0
  114. package/src/compliance/index.ts +23 -0
  115. package/src/compliance/range-sas.ts +398 -33
  116. package/src/config/endpoints.ts +100 -0
  117. package/src/crypto.ts +11 -8
  118. package/src/errors.ts +82 -0
  119. package/src/evm/erc4337-relayer.ts +830 -0
  120. package/src/evm/index.ts +47 -0
  121. package/src/fees/calculator.ts +396 -0
  122. package/src/fees/index.ts +87 -0
  123. package/src/fees/near-contract.ts +429 -0
  124. package/src/fees/types.ts +268 -0
  125. package/src/index.ts +686 -1
  126. package/src/intent.ts +6 -3
  127. package/src/logger.ts +324 -0
  128. package/src/network/index.ts +80 -0
  129. package/src/network/proxy.ts +691 -0
  130. package/src/optimizations/index.ts +541 -0
  131. package/src/oracle/types.ts +1 -0
  132. package/src/privacy-backends/arcium-types.ts +727 -0
  133. package/src/privacy-backends/arcium.ts +719 -0
  134. package/src/privacy-backends/combined-privacy.ts +866 -0
  135. package/src/privacy-backends/cspl-token.ts +595 -0
  136. package/src/privacy-backends/cspl-types.ts +512 -0
  137. package/src/privacy-backends/cspl.ts +907 -0
  138. package/src/privacy-backends/health.ts +488 -0
  139. package/src/privacy-backends/inco-types.ts +323 -0
  140. package/src/privacy-backends/inco.ts +616 -0
  141. package/src/privacy-backends/index.ts +254 -4
  142. package/src/privacy-backends/interface.ts +649 -6
  143. package/src/privacy-backends/lru-cache.ts +343 -0
  144. package/src/privacy-backends/magicblock.ts +458 -0
  145. package/src/privacy-backends/mock.ts +258 -0
  146. package/src/privacy-backends/privacycash.ts +13 -17
  147. package/src/privacy-backends/private-swap.ts +570 -0
  148. package/src/privacy-backends/rate-limiter.ts +683 -0
  149. package/src/privacy-backends/registry.ts +414 -2
  150. package/src/privacy-backends/router.ts +283 -3
  151. package/src/privacy-backends/shadowwire.ts +449 -0
  152. package/src/privacy-backends/sip-native.ts +3 -0
  153. package/src/privacy-logger.ts +191 -0
  154. package/src/production-safety.ts +373 -0
  155. package/src/proofs/aggregator.ts +1029 -0
  156. package/src/proofs/browser-composer.ts +1150 -0
  157. package/src/proofs/browser.ts +113 -25
  158. package/src/proofs/cache/index.ts +127 -0
  159. package/src/proofs/cache/interface.ts +545 -0
  160. package/src/proofs/cache/key-generator.ts +188 -0
  161. package/src/proofs/cache/lru-cache.ts +481 -0
  162. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  163. package/src/proofs/cache/persistent-cache.ts +788 -0
  164. package/src/proofs/compliance-proof.ts +872 -0
  165. package/src/proofs/composer/base.ts +923 -0
  166. package/src/proofs/composer/index.ts +25 -0
  167. package/src/proofs/composer/interface.ts +518 -0
  168. package/src/proofs/composer/types.ts +383 -0
  169. package/src/proofs/converters/halo2.ts +452 -0
  170. package/src/proofs/converters/index.ts +208 -0
  171. package/src/proofs/converters/interface.ts +363 -0
  172. package/src/proofs/converters/kimchi.ts +462 -0
  173. package/src/proofs/converters/noir.ts +451 -0
  174. package/src/proofs/fallback.ts +888 -0
  175. package/src/proofs/halo2.ts +42 -0
  176. package/src/proofs/index.ts +471 -0
  177. package/src/proofs/interface.ts +13 -0
  178. package/src/proofs/kimchi.ts +42 -0
  179. package/src/proofs/lazy.ts +1004 -0
  180. package/src/proofs/mock.ts +25 -1
  181. package/src/proofs/noir.ts +110 -29
  182. package/src/proofs/orchestrator.ts +960 -0
  183. package/src/proofs/parallel/concurrency.ts +297 -0
  184. package/src/proofs/parallel/dependency-graph.ts +602 -0
  185. package/src/proofs/parallel/executor.ts +420 -0
  186. package/src/proofs/parallel/index.ts +131 -0
  187. package/src/proofs/parallel/interface.ts +685 -0
  188. package/src/proofs/parallel/worker-pool.ts +644 -0
  189. package/src/proofs/providers/halo2.ts +560 -0
  190. package/src/proofs/providers/index.ts +34 -0
  191. package/src/proofs/providers/kimchi.ts +641 -0
  192. package/src/proofs/validator.ts +881 -0
  193. package/src/proofs/verifier.ts +867 -0
  194. package/src/quantum/index.ts +112 -0
  195. package/src/quantum/winternitz-vault.ts +639 -0
  196. package/src/quantum/wots.ts +611 -0
  197. package/src/settlement/backends/direct-chain.ts +1 -0
  198. package/src/settlement/index.ts +9 -0
  199. package/src/settlement/router.ts +732 -46
  200. package/src/solana/index.ts +72 -0
  201. package/src/solana/jito-relayer.ts +687 -0
  202. package/src/solana/noir-verifier-types.ts +430 -0
  203. package/src/solana/noir-verifier.ts +816 -0
  204. package/src/stealth/address-derivation.ts +193 -0
  205. package/src/stealth/ed25519.ts +431 -0
  206. package/src/stealth/index.ts +233 -0
  207. package/src/stealth/meta-address.ts +221 -0
  208. package/src/stealth/secp256k1.ts +368 -0
  209. package/src/stealth/utils.ts +194 -0
  210. package/src/stealth.ts +50 -1504
  211. package/src/sync/index.ts +106 -0
  212. package/src/sync/manager.ts +504 -0
  213. package/src/sync/mock-provider.ts +318 -0
  214. package/src/sync/oblivious.ts +625 -0
  215. package/src/tokens/index.ts +15 -0
  216. package/src/tokens/registry.ts +301 -0
  217. package/src/utils/deprecation.ts +94 -0
  218. package/src/utils/index.ts +9 -0
  219. package/src/wallet/ethereum/index.ts +68 -0
  220. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  221. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  222. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  223. package/src/wallet/ethereum/types.ts +3 -1
  224. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  225. package/src/wallet/hardware/index.ts +10 -0
  226. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  227. package/src/wallet/index.ts +71 -0
  228. package/src/wallet/near/adapter.ts +626 -0
  229. package/src/wallet/near/index.ts +86 -0
  230. package/src/wallet/near/meteor-wallet.ts +1153 -0
  231. package/src/wallet/near/my-near-wallet.ts +790 -0
  232. package/src/wallet/near/wallet-selector.ts +702 -0
  233. package/src/wallet/solana/adapter.ts +6 -4
  234. package/src/wallet/solana/index.ts +13 -0
  235. package/src/wallet/solana/privacy-adapter.ts +567 -0
  236. package/src/wallet/sui/types.ts +6 -4
  237. package/src/zcash/rpc-client.ts +13 -6
  238. package/dist/chunk-2XIVXWHA.mjs +0 -1930
  239. package/dist/chunk-3INS3PR5.mjs +0 -884
  240. package/dist/chunk-3OVABDRH.mjs +0 -17096
  241. package/dist/chunk-7RFRWDCW.mjs +0 -1504
  242. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  243. package/dist/chunk-E6SZWREQ.mjs +0 -57
  244. package/dist/chunk-F6F73W35.mjs +0 -16166
  245. package/dist/chunk-G33LB27A.mjs +0 -16166
  246. package/dist/chunk-HGU6HZRC.mjs +0 -231
  247. package/dist/chunk-L2K34JCU.mjs +0 -1496
  248. package/dist/chunk-OFDBEIEK.mjs +0 -16166
  249. package/dist/chunk-SF7YSLF5.mjs +0 -1515
  250. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  251. package/dist/chunk-WWUSGOXE.mjs +0 -17129
  252. package/dist/constants-VOI7BSLK.mjs +0 -27
  253. package/dist/index-B71aXVzk.d.ts +0 -13264
  254. package/dist/index-BYZbDjal.d.ts +0 -11390
  255. package/dist/index-CHB3KuOB.d.mts +0 -11859
  256. package/dist/index-CzWPI6Le.d.ts +0 -11859
  257. package/dist/index-pOIIuwfV.d.mts +0 -13264
  258. package/dist/index-xbWjohNq.d.mts +0 -11390
  259. package/dist/solana-4O4K45VU.mjs +0 -46
  260. package/dist/solana-5EMCTPTS.mjs +0 -46
  261. package/dist/solana-NDABAZ6P.mjs +0 -56
  262. package/dist/solana-Q4NAVBTS.mjs +0 -46
  263. package/dist/solana-ZYO63LY5.mjs +0 -46
@@ -0,0 +1,614 @@
1
+ /**
2
+ * Ethereum/EVM Chain-Specific Optimizations
3
+ *
4
+ * Provides optimized configurations for EVM transactions:
5
+ * - Gas optimization strategies
6
+ * - Storage packing recommendations
7
+ * - L2-specific optimizations (Arbitrum, Optimism, Base)
8
+ * - EIP-4844 blob transaction support
9
+ * - Batch transaction strategies
10
+ *
11
+ * @module chains/ethereum/optimizations
12
+ */
13
+
14
+ import {
15
+ DEFAULT_GAS_LIMITS,
16
+ ONE_GWEI,
17
+ ONE_ETH,
18
+ type EthereumNetwork,
19
+ isL2Network,
20
+ } from './constants'
21
+
22
+ // ─── Types ────────────────────────────────────────────────────────────────────
23
+
24
+ /**
25
+ * Gas optimization profile
26
+ */
27
+ export type GasProfile =
28
+ | 'economy' // Wait for lower gas, may take longer
29
+ | 'standard' // Balanced cost/speed
30
+ | 'fast' // Higher gas, faster confirmation
31
+ | 'instant' // Maximum priority, immediate confirmation
32
+
33
+ /**
34
+ * L2 optimization strategy
35
+ */
36
+ export type L2Strategy =
37
+ | 'calldata' // Optimize calldata encoding
38
+ | 'blob' // Use EIP-4844 blobs (where supported)
39
+ | 'compressed' // Use compression for calldata
40
+ | 'batched' // Batch multiple operations
41
+
42
+ /**
43
+ * Transaction complexity estimate for EVM
44
+ */
45
+ export interface EVMTransactionComplexity {
46
+ /** Estimated gas limit */
47
+ estimatedGas: bigint
48
+ /** Calldata size in bytes */
49
+ calldataSize: number
50
+ /** Number of storage slots written */
51
+ storageWrites: number
52
+ /** Number of storage slots read */
53
+ storageReads: number
54
+ /** Number of external calls */
55
+ externalCalls: number
56
+ /** Whether multicall is recommended */
57
+ multicallRecommended: boolean
58
+ }
59
+
60
+ /**
61
+ * Gas estimate with L2 considerations
62
+ */
63
+ export interface L2GasEstimate {
64
+ /** L2 execution gas */
65
+ l2Gas: bigint
66
+ /** L1 data/security gas (for rollups) */
67
+ l1DataGas: bigint
68
+ /** Total gas */
69
+ totalGas: bigint
70
+ /** L1 data cost in wei (for rollups) */
71
+ l1DataCostWei: bigint
72
+ /** Total estimated cost in wei */
73
+ totalCostWei: bigint
74
+ }
75
+
76
+ /**
77
+ * EVM optimization result
78
+ */
79
+ export interface EVMOptimizationResult {
80
+ /** Recommended gas limit */
81
+ gasLimit: bigint
82
+ /** Recommended max fee per gas */
83
+ maxFeePerGas: bigint
84
+ /** Recommended max priority fee */
85
+ maxPriorityFeePerGas: bigint
86
+ /** L2-specific estimate (if applicable) */
87
+ l2Estimate?: L2GasEstimate
88
+ /** Recommended strategies */
89
+ strategies: string[]
90
+ /** Whether to use multicall */
91
+ useMulticall: boolean
92
+ /** Whether to use EIP-4844 blobs */
93
+ useBlobs: boolean
94
+ }
95
+
96
+ /**
97
+ * Storage packing recommendation
98
+ */
99
+ export interface StoragePackingAdvice {
100
+ /** Current storage slots used */
101
+ currentSlots: number
102
+ /** Optimized slots (after packing) */
103
+ optimizedSlots: number
104
+ /** Gas savings estimate */
105
+ gasSavings: bigint
106
+ /** Recommendations */
107
+ recommendations: string[]
108
+ }
109
+
110
+ // ─── Constants ────────────────────────────────────────────────────────────────
111
+
112
+ /**
113
+ * Gas costs for common EVM operations
114
+ */
115
+ export const EVM_GAS_COSTS = {
116
+ /** Base transaction cost */
117
+ txBase: 21000n,
118
+ /** Zero byte in calldata */
119
+ calldataZeroByte: 4n,
120
+ /** Non-zero byte in calldata */
121
+ calldataNonZeroByte: 16n,
122
+ /** Storage read (cold) */
123
+ sloadCold: 2100n,
124
+ /** Storage read (warm) */
125
+ sloadWarm: 100n,
126
+ /** Storage write (zero to non-zero) */
127
+ sstoreSet: 20000n,
128
+ /** Storage write (non-zero to non-zero) */
129
+ sstoreUpdate: 5000n,
130
+ /** Storage write (non-zero to zero, refund) */
131
+ sstoreClear: -15000n, // Refund
132
+ /** External call (cold address) */
133
+ callCold: 2600n,
134
+ /** External call (warm address) */
135
+ callWarm: 100n,
136
+ /** Log (base) */
137
+ logBase: 375n,
138
+ /** Log per topic */
139
+ logTopic: 375n,
140
+ /** Log per byte */
141
+ logByte: 8n,
142
+ /** keccak256 per word */
143
+ keccak256Word: 6n,
144
+ /** Memory expansion per word */
145
+ memoryWord: 3n,
146
+ } as const
147
+
148
+ /**
149
+ * Profile multipliers for gas price
150
+ */
151
+ const GAS_PROFILE_MULTIPLIERS: Record<GasProfile, number> = {
152
+ economy: 0.8,
153
+ standard: 1.0,
154
+ fast: 1.5,
155
+ instant: 2.5,
156
+ }
157
+
158
+ /**
159
+ * L2 data gas multipliers (approximate)
160
+ * L2s charge for L1 data posting differently
161
+ */
162
+ const L2_DATA_MULTIPLIERS: Partial<Record<EthereumNetwork, number>> = {
163
+ arbitrum: 16, // ~16x L1 calldata cost
164
+ 'arbitrum-sepolia': 16,
165
+ optimism: 16,
166
+ 'optimism-sepolia': 16,
167
+ base: 16,
168
+ 'base-sepolia': 16,
169
+ zksync: 1, // Different model
170
+ scroll: 16,
171
+ linea: 16,
172
+ mantle: 4, // Lower data costs
173
+ blast: 16,
174
+ }
175
+
176
+
177
+ // ─── Gas Estimation ───────────────────────────────────────────────────────────
178
+
179
+ /**
180
+ * Estimate gas for privacy transaction
181
+ *
182
+ * @param options - Transaction options
183
+ * @returns Transaction complexity estimate
184
+ */
185
+ export function estimatePrivacyTxComplexity(options: {
186
+ /** Number of transfers */
187
+ transferCount: number
188
+ /** Whether includes ERC-20 approval */
189
+ includesApproval: boolean
190
+ /** Whether includes announcement */
191
+ includesAnnouncement: boolean
192
+ /** Custom calldata size */
193
+ customCalldataSize?: number
194
+ }): EVMTransactionComplexity {
195
+ let estimatedGas = EVM_GAS_COSTS.txBase
196
+
197
+ // Transfer gas
198
+ if (options.transferCount > 0) {
199
+ // ERC-20 transfer: storage read + storage write + emit event
200
+ const perTransfer =
201
+ EVM_GAS_COSTS.sloadCold + // Balance read
202
+ EVM_GAS_COSTS.sstoreUpdate + // Balance update sender
203
+ EVM_GAS_COSTS.sstoreUpdate + // Balance update receiver
204
+ EVM_GAS_COSTS.logBase +
205
+ EVM_GAS_COSTS.logTopic * 3n + // Transfer event
206
+ EVM_GAS_COSTS.callCold // External call to token
207
+
208
+ estimatedGas += perTransfer * BigInt(options.transferCount)
209
+ }
210
+
211
+ // Approval gas
212
+ if (options.includesApproval) {
213
+ estimatedGas +=
214
+ EVM_GAS_COSTS.sstoreSet + // Allowance storage
215
+ EVM_GAS_COSTS.logBase +
216
+ EVM_GAS_COSTS.logTopic * 3n // Approval event
217
+ }
218
+
219
+ // Announcement gas
220
+ if (options.includesAnnouncement) {
221
+ estimatedGas += DEFAULT_GAS_LIMITS.announcement
222
+ }
223
+
224
+ // Calldata estimation
225
+ const baseCalldata = 4 + 32 * 3 // Function selector + 3 params
226
+ const perTransferCalldata = 32 * 2 // Address + amount
227
+ const calldataSize =
228
+ options.customCalldataSize ??
229
+ baseCalldata + perTransferCalldata * options.transferCount
230
+
231
+ return {
232
+ estimatedGas,
233
+ calldataSize,
234
+ storageWrites: options.transferCount * 2 + (options.includesApproval ? 1 : 0),
235
+ storageReads: options.transferCount * 2,
236
+ externalCalls: options.transferCount + (options.includesApproval ? 1 : 0),
237
+ multicallRecommended: options.transferCount > 2,
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Calculate L2 gas estimate with L1 data costs
243
+ *
244
+ * @param network - Target L2 network
245
+ * @param complexity - Transaction complexity
246
+ * @param l2GasPrice - L2 gas price in wei
247
+ * @param l1BaseFee - L1 base fee in wei (for data cost calculation)
248
+ * @returns L2 gas estimate
249
+ */
250
+ export function calculateL2GasEstimate(
251
+ network: EthereumNetwork,
252
+ complexity: EVMTransactionComplexity,
253
+ l2GasPrice: bigint,
254
+ l1BaseFee: bigint
255
+ ): L2GasEstimate {
256
+ const multiplier = L2_DATA_MULTIPLIERS[network] ?? 1
257
+
258
+ // L2 execution gas
259
+ const l2Gas = complexity.estimatedGas
260
+
261
+ // L1 data gas (calldata posted to L1)
262
+ // Approximate: each non-zero byte costs 16 L1 gas, zero byte costs 4
263
+ // Assume 70% non-zero bytes for typical transactions
264
+ const nonZeroBytes = Math.ceil(complexity.calldataSize * 0.7)
265
+ const zeroBytes = complexity.calldataSize - nonZeroBytes
266
+ const l1CalldataGas =
267
+ BigInt(nonZeroBytes) * EVM_GAS_COSTS.calldataNonZeroByte +
268
+ BigInt(zeroBytes) * EVM_GAS_COSTS.calldataZeroByte
269
+
270
+ // L1 data gas scaled by multiplier
271
+ const l1DataGas = l1CalldataGas * BigInt(multiplier)
272
+
273
+ // Total gas
274
+ const totalGas = l2Gas + l1DataGas
275
+
276
+ // Cost calculation
277
+ const l2Cost = l2Gas * l2GasPrice
278
+ const l1DataCostWei = l1DataGas * l1BaseFee
279
+ const totalCostWei = l2Cost + l1DataCostWei
280
+
281
+ return {
282
+ l2Gas,
283
+ l1DataGas,
284
+ totalGas,
285
+ l1DataCostWei,
286
+ totalCostWei,
287
+ }
288
+ }
289
+
290
+ // ─── Optimization Functions ───────────────────────────────────────────────────
291
+
292
+ /**
293
+ * Get full optimization result for a transaction
294
+ *
295
+ * @param network - Target network
296
+ * @param complexity - Transaction complexity
297
+ * @param profile - Gas profile
298
+ * @param baseFee - Current base fee
299
+ * @param l1BaseFee - L1 base fee (for L2 networks)
300
+ * @returns Optimization result
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * const complexity = estimatePrivacyTxComplexity({
305
+ * transferCount: 1,
306
+ * includesApproval: true,
307
+ * includesAnnouncement: true
308
+ * })
309
+ *
310
+ * const result = optimizeTransaction('arbitrum', complexity, 'standard', baseFee)
311
+ * console.log(result.gasLimit) // Recommended gas limit
312
+ * ```
313
+ */
314
+ export function optimizeTransaction(
315
+ network: EthereumNetwork,
316
+ complexity: EVMTransactionComplexity,
317
+ profile: GasProfile = 'standard',
318
+ baseFee: bigint,
319
+ l1BaseFee?: bigint
320
+ ): EVMOptimizationResult {
321
+ const multiplier = GAS_PROFILE_MULTIPLIERS[profile]
322
+
323
+ // Add 20% buffer to gas estimate
324
+ const gasLimit = (complexity.estimatedGas * 120n) / 100n
325
+
326
+ // Priority fee based on profile
327
+ const basePriorityFee = ONE_GWEI * 2n // 2 gwei base
328
+ const maxPriorityFeePerGas = BigInt(
329
+ Math.ceil(Number(basePriorityFee) * multiplier)
330
+ )
331
+
332
+ // Max fee = base fee * 2 + priority (for price stability)
333
+ const maxFeePerGas = baseFee * 2n + maxPriorityFeePerGas
334
+
335
+ const strategies: string[] = []
336
+ let l2Estimate: L2GasEstimate | undefined
337
+
338
+ // L2-specific optimizations
339
+ if (isL2Network(network)) {
340
+ if (l1BaseFee) {
341
+ l2Estimate = calculateL2GasEstimate(
342
+ network,
343
+ complexity,
344
+ maxFeePerGas,
345
+ l1BaseFee
346
+ )
347
+ }
348
+
349
+ strategies.push('Compress calldata for lower L1 data costs')
350
+
351
+ if (complexity.calldataSize > 500) {
352
+ strategies.push('Consider batching to amortize L1 data overhead')
353
+ }
354
+ }
355
+
356
+ // Multicall recommendation
357
+ if (complexity.multicallRecommended) {
358
+ strategies.push('Use multicall to batch operations in single transaction')
359
+ }
360
+
361
+ // Storage optimization
362
+ if (complexity.storageWrites > 3) {
363
+ strategies.push(
364
+ 'Minimize storage writes - each write costs 5000+ gas'
365
+ )
366
+ }
367
+
368
+ // EIP-4844 blob consideration (for large data)
369
+ const useBlobs =
370
+ complexity.calldataSize > 10000 && supportsEIP4844(network)
371
+
372
+ if (useBlobs) {
373
+ strategies.push('Use EIP-4844 blobs for cheaper large data posting')
374
+ }
375
+
376
+ return {
377
+ gasLimit,
378
+ maxFeePerGas,
379
+ maxPriorityFeePerGas,
380
+ l2Estimate,
381
+ strategies,
382
+ useMulticall: complexity.multicallRecommended,
383
+ useBlobs,
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Check if network supports EIP-4844 blobs
389
+ */
390
+ export function supportsEIP4844(network: EthereumNetwork): boolean {
391
+ // EIP-4844 (Dencun) is live on mainnet and major L2s
392
+ const supported: EthereumNetwork[] = [
393
+ 'mainnet',
394
+ 'sepolia',
395
+ 'arbitrum',
396
+ 'arbitrum-sepolia',
397
+ 'optimism',
398
+ 'optimism-sepolia',
399
+ 'base',
400
+ 'base-sepolia',
401
+ ]
402
+ return supported.includes(network)
403
+ }
404
+
405
+ // ─── Batch Optimization ───────────────────────────────────────────────────────
406
+
407
+ /**
408
+ * Calculate optimal batch size for multiple operations
409
+ *
410
+ * @param operationCount - Total operations
411
+ * @param network - Target network
412
+ * @param options - Batch options
413
+ * @returns Array of batch sizes
414
+ */
415
+ export function calculateOptimalBatches(
416
+ operationCount: number,
417
+ network: EthereumNetwork,
418
+ options: {
419
+ /** Max gas per transaction */
420
+ maxGasPerTx?: bigint
421
+ /** Gas per operation */
422
+ gasPerOperation?: bigint
423
+ } = {}
424
+ ): number[] {
425
+ const {
426
+ maxGasPerTx = isL2Network(network) ? 3_000_000n : 15_000_000n,
427
+ gasPerOperation = DEFAULT_GAS_LIMITS.erc20Transfer,
428
+ } = options
429
+
430
+ // Account for base gas
431
+ const availableGas = maxGasPerTx - EVM_GAS_COSTS.txBase
432
+ const maxOpsPerBatch = Number(availableGas / gasPerOperation)
433
+
434
+ const batches: number[] = []
435
+ let remaining = operationCount
436
+
437
+ while (remaining > 0) {
438
+ const batchSize = Math.min(remaining, maxOpsPerBatch)
439
+ batches.push(batchSize)
440
+ remaining -= batchSize
441
+ }
442
+
443
+ return batches
444
+ }
445
+
446
+ // ─── Storage Packing ──────────────────────────────────────────────────────────
447
+
448
+ /**
449
+ * Analyze storage packing opportunities
450
+ *
451
+ * Ethereum storage is organized in 32-byte slots.
452
+ * Packing multiple values into single slots saves gas.
453
+ *
454
+ * @param variables - Array of variable sizes in bytes
455
+ * @returns Storage packing advice
456
+ */
457
+ export function analyzeStoragePacking(
458
+ variables: Array<{ name: string; size: number }>
459
+ ): StoragePackingAdvice {
460
+ // Current: each variable gets its own slot
461
+ const currentSlots = variables.length
462
+
463
+ // Optimized: pack variables into slots
464
+ const SLOT_SIZE = 32
465
+ let optimizedSlots = 0
466
+ let currentSlotRemaining = SLOT_SIZE
467
+
468
+ // Sort by size (largest first) for better packing
469
+ const sorted = [...variables].sort((a, b) => b.size - a.size)
470
+
471
+ for (const variable of sorted) {
472
+ if (variable.size > currentSlotRemaining) {
473
+ optimizedSlots++
474
+ currentSlotRemaining = SLOT_SIZE
475
+ }
476
+ currentSlotRemaining -= variable.size
477
+ }
478
+
479
+ if (currentSlotRemaining < SLOT_SIZE) {
480
+ optimizedSlots++
481
+ }
482
+
483
+ // Calculate gas savings
484
+ // SSTORE for new slot: 20000 gas
485
+ // Reading additional slots: 2100 gas each (cold)
486
+ const slotsSaved = currentSlots - optimizedSlots
487
+ const gasSavings = BigInt(slotsSaved) * EVM_GAS_COSTS.sstoreSet
488
+
489
+ const recommendations: string[] = []
490
+
491
+ if (slotsSaved > 0) {
492
+ recommendations.push(
493
+ `Pack variables to save ${slotsSaved} storage slots (~${gasSavings} gas on writes)`
494
+ )
495
+
496
+ // Specific packing recommendations
497
+ const smallVars = variables.filter((v) => v.size <= 16)
498
+ if (smallVars.length >= 2) {
499
+ recommendations.push(
500
+ `Pack small variables (${smallVars.map((v) => v.name).join(', ')}) into single slot`
501
+ )
502
+ }
503
+ }
504
+
505
+ return {
506
+ currentSlots,
507
+ optimizedSlots,
508
+ gasSavings,
509
+ recommendations,
510
+ }
511
+ }
512
+
513
+ // ─── Utility Functions ────────────────────────────────────────────────────────
514
+
515
+ /**
516
+ * Convert wei to ETH
517
+ */
518
+ export function weiToEth(wei: bigint): string {
519
+ const eth = Number(wei) / Number(ONE_ETH)
520
+ return eth.toFixed(6)
521
+ }
522
+
523
+ /**
524
+ * Convert gwei to wei
525
+ */
526
+ export function gweiToWei(gwei: number): bigint {
527
+ return BigInt(Math.floor(gwei * 1e9))
528
+ }
529
+
530
+ /**
531
+ * Format gas price for display
532
+ */
533
+ export function formatGasPrice(wei: bigint): string {
534
+ const gwei = Number(wei) / 1e9
535
+ if (gwei < 0.01) {
536
+ return `${(gwei * 1000).toFixed(2)} mGwei`
537
+ }
538
+ return `${gwei.toFixed(2)} Gwei`
539
+ }
540
+
541
+ /**
542
+ * Get gas profile from user-friendly name
543
+ */
544
+ export function parseGasProfile(name: string): GasProfile {
545
+ const normalized = name.toLowerCase().trim()
546
+ switch (normalized) {
547
+ case 'economy':
548
+ case 'eco':
549
+ case 'low':
550
+ case 'slow':
551
+ return 'economy'
552
+ case 'standard':
553
+ case 'normal':
554
+ case 'default':
555
+ case 'medium':
556
+ return 'standard'
557
+ case 'fast':
558
+ case 'high':
559
+ case 'quick':
560
+ return 'fast'
561
+ case 'instant':
562
+ case 'max':
563
+ case 'urgent':
564
+ case 'turbo':
565
+ return 'instant'
566
+ default:
567
+ return 'standard'
568
+ }
569
+ }
570
+
571
+ /**
572
+ * Estimate calldata cost
573
+ *
574
+ * @param data - Calldata bytes
575
+ * @returns Gas cost for calldata
576
+ */
577
+ export function estimateCalldataCost(data: Uint8Array | string): bigint {
578
+ const bytes =
579
+ typeof data === 'string'
580
+ ? Uint8Array.from(Buffer.from(data.replace('0x', ''), 'hex'))
581
+ : data
582
+
583
+ let cost = 0n
584
+ for (const byte of bytes) {
585
+ cost += byte === 0 ? EVM_GAS_COSTS.calldataZeroByte : EVM_GAS_COSTS.calldataNonZeroByte
586
+ }
587
+ return cost
588
+ }
589
+
590
+ /**
591
+ * Compare gas costs between networks
592
+ *
593
+ * @param complexity - Transaction complexity
594
+ * @param networks - Networks to compare
595
+ * @param gasPrices - Gas prices per network (wei)
596
+ * @returns Cost comparison
597
+ */
598
+ export function compareNetworkCosts(
599
+ complexity: EVMTransactionComplexity,
600
+ networks: EthereumNetwork[],
601
+ gasPrices: Record<EthereumNetwork, bigint>
602
+ ): Array<{ network: EthereumNetwork; costWei: bigint; costEth: string }> {
603
+ return networks
604
+ .map((network) => {
605
+ const gasPrice = gasPrices[network] ?? ONE_GWEI * 10n
606
+ const costWei = complexity.estimatedGas * gasPrice
607
+ return {
608
+ network,
609
+ costWei,
610
+ costEth: weiToEth(costWei),
611
+ }
612
+ })
613
+ .sort((a, b) => (a.costWei < b.costWei ? -1 : 1))
614
+ }