@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.
Files changed (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
  4. package/dist/browser.d.mts +10 -4
  5. package/dist/browser.d.ts +10 -4
  6. package/dist/browser.js +47556 -19603
  7. package/dist/browser.mjs +628 -48
  8. package/dist/chunk-4GRJ5MAW.mjs +152 -0
  9. package/dist/chunk-5D7A3L3W.mjs +717 -0
  10. package/dist/chunk-64AYA5F5.mjs +7834 -0
  11. package/dist/chunk-GMDGB22A.mjs +379 -0
  12. package/dist/chunk-I534WKN7.mjs +328 -0
  13. package/dist/chunk-IBZVA5Y7.mjs +1003 -0
  14. package/dist/chunk-PRRZAWJE.mjs +223 -0
  15. package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
  16. package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
  17. package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
  18. package/dist/constants-LHAAUC2T.mjs +51 -0
  19. package/dist/dist-2OGQ7FED.mjs +3957 -0
  20. package/dist/dist-IFHPYLDX.mjs +254 -0
  21. package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
  22. package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
  23. package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
  24. package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48396 -19623
  28. package/dist/index.mjs +537 -19
  29. package/dist/interface-Bf7w1PLW.d.mts +679 -0
  30. package/dist/interface-Bf7w1PLW.d.ts +679 -0
  31. package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
  32. package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
  33. package/dist/proofs/halo2.d.mts +151 -0
  34. package/dist/proofs/halo2.d.ts +151 -0
  35. package/dist/proofs/halo2.js +350 -0
  36. package/dist/proofs/halo2.mjs +11 -0
  37. package/dist/proofs/kimchi.d.mts +160 -0
  38. package/dist/proofs/kimchi.d.ts +160 -0
  39. package/dist/proofs/kimchi.js +431 -0
  40. package/dist/proofs/kimchi.mjs +13 -0
  41. package/dist/proofs/noir.d.mts +1 -1
  42. package/dist/proofs/noir.d.ts +1 -1
  43. package/dist/proofs/noir.js +74 -18
  44. package/dist/proofs/noir.mjs +84 -24
  45. package/dist/solana-U3MEGU7W.mjs +280 -0
  46. package/dist/validity_proof-3POXLPNY.mjs +21 -0
  47. package/package.json +54 -21
  48. package/src/adapters/index.ts +41 -0
  49. package/src/adapters/jupiter.ts +571 -0
  50. package/src/adapters/near-intents.ts +135 -0
  51. package/src/advisor/advisor.ts +653 -0
  52. package/src/advisor/index.ts +54 -0
  53. package/src/advisor/tools.ts +303 -0
  54. package/src/advisor/types.ts +164 -0
  55. package/src/chains/ethereum/announcement.ts +536 -0
  56. package/src/chains/ethereum/bnb-optimizations.ts +474 -0
  57. package/src/chains/ethereum/commitment.ts +522 -0
  58. package/src/chains/ethereum/constants.ts +462 -0
  59. package/src/chains/ethereum/deployment.ts +596 -0
  60. package/src/chains/ethereum/gas-estimation.ts +538 -0
  61. package/src/chains/ethereum/index.ts +268 -0
  62. package/src/chains/ethereum/optimizations.ts +614 -0
  63. package/src/chains/ethereum/privacy-adapter.ts +855 -0
  64. package/src/chains/ethereum/registry.ts +584 -0
  65. package/src/chains/ethereum/rpc.ts +905 -0
  66. package/src/chains/ethereum/stealth.ts +491 -0
  67. package/src/chains/ethereum/token.ts +790 -0
  68. package/src/chains/ethereum/transfer.ts +637 -0
  69. package/src/chains/ethereum/types.ts +456 -0
  70. package/src/chains/ethereum/viewing-key.ts +455 -0
  71. package/src/chains/near/commitment.ts +608 -0
  72. package/src/chains/near/constants.ts +284 -0
  73. package/src/chains/near/function-call.ts +871 -0
  74. package/src/chains/near/history.ts +654 -0
  75. package/src/chains/near/implicit-account.ts +840 -0
  76. package/src/chains/near/index.ts +393 -0
  77. package/src/chains/near/native-transfer.ts +658 -0
  78. package/src/chains/near/nep141.ts +775 -0
  79. package/src/chains/near/privacy-adapter.ts +889 -0
  80. package/src/chains/near/resolver.ts +971 -0
  81. package/src/chains/near/rpc.ts +1016 -0
  82. package/src/chains/near/stealth.ts +419 -0
  83. package/src/chains/near/types.ts +317 -0
  84. package/src/chains/near/viewing-key.ts +876 -0
  85. package/src/chains/solana/anchor-transfer.ts +386 -0
  86. package/src/chains/solana/commitment.ts +577 -0
  87. package/src/chains/solana/constants.ts +126 -12
  88. package/src/chains/solana/ephemeral-keys.ts +543 -0
  89. package/src/chains/solana/index.ts +252 -1
  90. package/src/chains/solana/key-derivation.ts +418 -0
  91. package/src/chains/solana/kit-compat.ts +334 -0
  92. package/src/chains/solana/optimizations.ts +560 -0
  93. package/src/chains/solana/privacy-adapter.ts +605 -0
  94. package/src/chains/solana/providers/generic.ts +47 -6
  95. package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
  96. package/src/chains/solana/providers/helius-enhanced.ts +623 -0
  97. package/src/chains/solana/providers/helius.ts +186 -33
  98. package/src/chains/solana/providers/index.ts +31 -0
  99. package/src/chains/solana/providers/interface.ts +61 -18
  100. package/src/chains/solana/providers/quicknode.ts +409 -0
  101. package/src/chains/solana/providers/triton.ts +426 -0
  102. package/src/chains/solana/providers/webhook.ts +338 -67
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +83 -66
  105. package/src/chains/solana/sol-transfer.ts +732 -0
  106. package/src/chains/solana/spl-transfer.ts +886 -0
  107. package/src/chains/solana/stealth-scanner.ts +703 -0
  108. package/src/chains/solana/sunspot-verifier.ts +453 -0
  109. package/src/chains/solana/transaction-builder.ts +755 -0
  110. package/src/chains/solana/transfer.ts +74 -5
  111. package/src/chains/solana/types.ts +57 -6
  112. package/src/chains/solana/utils.ts +110 -0
  113. package/src/chains/solana/viewing-key.ts +807 -0
  114. package/src/compliance/fireblocks.ts +921 -0
  115. package/src/compliance/index.ts +23 -0
  116. package/src/compliance/range-sas.ts +398 -33
  117. package/src/config/endpoints.ts +100 -0
  118. package/src/crypto.ts +11 -8
  119. package/src/errors.ts +82 -0
  120. package/src/evm/erc4337-relayer.ts +830 -0
  121. package/src/evm/index.ts +47 -0
  122. package/src/fees/calculator.ts +396 -0
  123. package/src/fees/index.ts +87 -0
  124. package/src/fees/near-contract.ts +429 -0
  125. package/src/fees/types.ts +268 -0
  126. package/src/index.ts +686 -1
  127. package/src/intent.ts +6 -3
  128. package/src/logger.ts +324 -0
  129. package/src/network/index.ts +80 -0
  130. package/src/network/proxy.ts +691 -0
  131. package/src/optimizations/index.ts +541 -0
  132. package/src/oracle/types.ts +1 -0
  133. package/src/privacy-backends/arcium-types.ts +727 -0
  134. package/src/privacy-backends/arcium.ts +719 -0
  135. package/src/privacy-backends/combined-privacy.ts +866 -0
  136. package/src/privacy-backends/cspl-token.ts +595 -0
  137. package/src/privacy-backends/cspl-types.ts +512 -0
  138. package/src/privacy-backends/cspl.ts +907 -0
  139. package/src/privacy-backends/health.ts +488 -0
  140. package/src/privacy-backends/inco-types.ts +323 -0
  141. package/src/privacy-backends/inco.ts +616 -0
  142. package/src/privacy-backends/index.ts +254 -4
  143. package/src/privacy-backends/interface.ts +649 -6
  144. package/src/privacy-backends/lru-cache.ts +343 -0
  145. package/src/privacy-backends/magicblock.ts +458 -0
  146. package/src/privacy-backends/mock.ts +258 -0
  147. package/src/privacy-backends/privacycash.ts +13 -17
  148. package/src/privacy-backends/private-swap.ts +570 -0
  149. package/src/privacy-backends/rate-limiter.ts +683 -0
  150. package/src/privacy-backends/registry.ts +414 -2
  151. package/src/privacy-backends/router.ts +283 -3
  152. package/src/privacy-backends/shadowwire.ts +449 -0
  153. package/src/privacy-backends/sip-native.ts +3 -0
  154. package/src/privacy-logger.ts +191 -0
  155. package/src/production-safety.ts +373 -0
  156. package/src/proofs/aggregator.ts +1029 -0
  157. package/src/proofs/browser-composer.ts +1150 -0
  158. package/src/proofs/browser.ts +113 -25
  159. package/src/proofs/cache/index.ts +127 -0
  160. package/src/proofs/cache/interface.ts +545 -0
  161. package/src/proofs/cache/key-generator.ts +188 -0
  162. package/src/proofs/cache/lru-cache.ts +481 -0
  163. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  164. package/src/proofs/cache/persistent-cache.ts +788 -0
  165. package/src/proofs/compliance-proof.ts +872 -0
  166. package/src/proofs/composer/base.ts +923 -0
  167. package/src/proofs/composer/index.ts +25 -0
  168. package/src/proofs/composer/interface.ts +518 -0
  169. package/src/proofs/composer/types.ts +383 -0
  170. package/src/proofs/converters/halo2.ts +452 -0
  171. package/src/proofs/converters/index.ts +208 -0
  172. package/src/proofs/converters/interface.ts +363 -0
  173. package/src/proofs/converters/kimchi.ts +462 -0
  174. package/src/proofs/converters/noir.ts +451 -0
  175. package/src/proofs/fallback.ts +888 -0
  176. package/src/proofs/halo2.ts +42 -0
  177. package/src/proofs/index.ts +471 -0
  178. package/src/proofs/interface.ts +13 -0
  179. package/src/proofs/kimchi.ts +42 -0
  180. package/src/proofs/lazy.ts +1004 -0
  181. package/src/proofs/mock.ts +25 -1
  182. package/src/proofs/noir.ts +110 -29
  183. package/src/proofs/orchestrator.ts +960 -0
  184. package/src/proofs/parallel/concurrency.ts +297 -0
  185. package/src/proofs/parallel/dependency-graph.ts +602 -0
  186. package/src/proofs/parallel/executor.ts +420 -0
  187. package/src/proofs/parallel/index.ts +131 -0
  188. package/src/proofs/parallel/interface.ts +685 -0
  189. package/src/proofs/parallel/worker-pool.ts +644 -0
  190. package/src/proofs/providers/halo2.ts +560 -0
  191. package/src/proofs/providers/index.ts +34 -0
  192. package/src/proofs/providers/kimchi.ts +641 -0
  193. package/src/proofs/validator.ts +881 -0
  194. package/src/proofs/verifier.ts +867 -0
  195. package/src/quantum/index.ts +112 -0
  196. package/src/quantum/winternitz-vault.ts +639 -0
  197. package/src/quantum/wots.ts +611 -0
  198. package/src/settlement/backends/direct-chain.ts +1 -0
  199. package/src/settlement/index.ts +9 -0
  200. package/src/settlement/router.ts +732 -46
  201. package/src/solana/index.ts +72 -0
  202. package/src/solana/jito-relayer.ts +687 -0
  203. package/src/solana/noir-verifier-types.ts +430 -0
  204. package/src/solana/noir-verifier.ts +816 -0
  205. package/src/stealth/address-derivation.ts +193 -0
  206. package/src/stealth/ed25519.ts +431 -0
  207. package/src/stealth/index.ts +233 -0
  208. package/src/stealth/meta-address.ts +221 -0
  209. package/src/stealth/secp256k1.ts +368 -0
  210. package/src/stealth/utils.ts +194 -0
  211. package/src/stealth.ts +50 -1504
  212. package/src/sync/index.ts +106 -0
  213. package/src/sync/manager.ts +504 -0
  214. package/src/sync/mock-provider.ts +318 -0
  215. package/src/sync/oblivious.ts +625 -0
  216. package/src/tokens/index.ts +15 -0
  217. package/src/tokens/registry.ts +301 -0
  218. package/src/utils/deprecation.ts +94 -0
  219. package/src/utils/index.ts +9 -0
  220. package/src/wallet/ethereum/index.ts +68 -0
  221. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  222. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  223. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  224. package/src/wallet/ethereum/types.ts +3 -1
  225. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  226. package/src/wallet/hardware/index.ts +10 -0
  227. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  228. package/src/wallet/index.ts +71 -0
  229. package/src/wallet/near/adapter.ts +626 -0
  230. package/src/wallet/near/index.ts +86 -0
  231. package/src/wallet/near/meteor-wallet.ts +1153 -0
  232. package/src/wallet/near/my-near-wallet.ts +790 -0
  233. package/src/wallet/near/wallet-selector.ts +702 -0
  234. package/src/wallet/solana/adapter.ts +6 -4
  235. package/src/wallet/solana/index.ts +13 -0
  236. package/src/wallet/solana/privacy-adapter.ts +567 -0
  237. package/src/wallet/sui/types.ts +6 -4
  238. package/src/zcash/rpc-client.ts +13 -6
  239. package/dist/chunk-2XIVXWHA.mjs +0 -1930
  240. package/dist/chunk-3INS3PR5.mjs +0 -884
  241. package/dist/chunk-3OVABDRH.mjs +0 -17096
  242. package/dist/chunk-7RFRWDCW.mjs +0 -1504
  243. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  244. package/dist/chunk-E6SZWREQ.mjs +0 -57
  245. package/dist/chunk-F6F73W35.mjs +0 -16166
  246. package/dist/chunk-G33LB27A.mjs +0 -16166
  247. package/dist/chunk-HGU6HZRC.mjs +0 -231
  248. package/dist/chunk-L2K34JCU.mjs +0 -1496
  249. package/dist/chunk-OFDBEIEK.mjs +0 -16166
  250. package/dist/chunk-SF7YSLF5.mjs +0 -1515
  251. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  252. package/dist/chunk-WWUSGOXE.mjs +0 -17129
  253. package/dist/constants-VOI7BSLK.mjs +0 -27
  254. package/dist/index-B71aXVzk.d.ts +0 -13264
  255. package/dist/index-BYZbDjal.d.ts +0 -11390
  256. package/dist/index-CHB3KuOB.d.mts +0 -11859
  257. package/dist/index-CzWPI6Le.d.ts +0 -11859
  258. package/dist/index-pOIIuwfV.d.mts +0 -13264
  259. package/dist/index-xbWjohNq.d.mts +0 -11390
  260. package/dist/solana-4O4K45VU.mjs +0 -46
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-NDABAZ6P.mjs +0 -56
  263. package/dist/solana-Q4NAVBTS.mjs +0 -46
  264. package/dist/solana-ZYO63LY5.mjs +0 -46
@@ -0,0 +1,608 @@
1
+ /**
2
+ * NEAR Pedersen Commitment Implementation
3
+ *
4
+ * Ed25519-based Pedersen commitments for NEP-141 token privacy on NEAR.
5
+ *
6
+ * ## Security Properties
7
+ *
8
+ * - **Hiding (Computational)**: Cannot determine value from commitment
9
+ * - **Binding (Computational)**: Cannot open commitment to different value
10
+ * - **Homomorphic**: C(v1) + C(v2) = C(v1 + v2) when blindings sum
11
+ *
12
+ * ## Ed25519 Curve
13
+ *
14
+ * This implementation uses ed25519 (Curve25519 in Edwards form) for
15
+ * compatibility with NEAR's native cryptography and implicit accounts.
16
+ *
17
+ * ## NEAR Token Amounts
18
+ *
19
+ * NEAR uses u128 for native NEAR (24 decimals) and u128 for NEP-141 tokens.
20
+ * Pedersen commitments operate on values < curve order (2^252 + ...).
21
+ *
22
+ * @module chains/near/commitment
23
+ */
24
+
25
+ import { ed25519 } from '@noble/curves/ed25519'
26
+ import { sha256 } from '@noble/hashes/sha2'
27
+ import { bytesToHex, randomBytes } from '@noble/hashes/utils'
28
+ import type { HexString } from '@sip-protocol/types'
29
+ import { ValidationError, CryptoError, ErrorCode } from '../../errors'
30
+ import { isValidHex } from '../../validation'
31
+
32
+ // ─── Types ────────────────────────────────────────────────────────────────────
33
+
34
+ /**
35
+ * A Pedersen commitment with associated blinding factor
36
+ */
37
+ export interface NEARPedersenCommitment {
38
+ /**
39
+ * The commitment point C = v*G + r*H (compressed ed25519, 32 bytes)
40
+ */
41
+ commitment: HexString
42
+
43
+ /**
44
+ * The blinding factor r (32 bytes, secret)
45
+ * Required to open/verify the commitment
46
+ */
47
+ blinding: HexString
48
+ }
49
+
50
+ /**
51
+ * A commitment point without the blinding factor (for public sharing)
52
+ */
53
+ export interface NEARCommitmentPoint {
54
+ /**
55
+ * The commitment point (compressed ed25519, 32 bytes)
56
+ */
57
+ commitment: HexString
58
+ }
59
+
60
+ /**
61
+ * NEP-141 token commitment with amount and token info
62
+ */
63
+ export interface NEP141TokenCommitment extends NEARPedersenCommitment {
64
+ /**
65
+ * NEP-141 token contract address
66
+ */
67
+ tokenContract: string
68
+
69
+ /**
70
+ * Token decimals (e.g., 24 for NEAR, 6 for USDC)
71
+ */
72
+ decimals: number
73
+
74
+ /**
75
+ * Original amount in smallest units (u128)
76
+ */
77
+ amountRaw?: bigint
78
+ }
79
+
80
+ // ─── Constants ────────────────────────────────────────────────────────────────
81
+
82
+ /**
83
+ * Domain separation tag for H generation (NEAR version)
84
+ */
85
+ const H_DOMAIN = 'SIP-NEAR-PEDERSEN-GENERATOR-H-v1'
86
+
87
+ /**
88
+ * The generator G (ed25519 base point)
89
+ */
90
+ const G = ed25519.ExtendedPoint.BASE
91
+
92
+ /**
93
+ * The ed25519 curve order L (number of points in the subgroup)
94
+ */
95
+ export const ED25519_ORDER = 2n ** 252n + 27742317777372353535851937790883648493n
96
+
97
+ /**
98
+ * Ed25519 cofactor (the curve has order 8*L where L is the prime subgroup order)
99
+ */
100
+ const ED25519_COFACTOR = 8n
101
+
102
+ /**
103
+ * Maximum NEAR amount (u128::MAX)
104
+ * Note: Actual NEAR total supply is much less, but u128 is the storage type
105
+ */
106
+ export const MAX_NEAR_AMOUNT = 2n ** 128n - 1n
107
+
108
+ /**
109
+ * Maximum value that can be committed (must be < curve order)
110
+ */
111
+ export const MAX_COMMITMENT_VALUE = ED25519_ORDER - 1n
112
+
113
+ // ─── Generator H Construction ─────────────────────────────────────────────────
114
+
115
+ /**
116
+ * The independent generator H (NUMS point)
117
+ * Constructed via hash-to-curve with nothing-up-my-sleeve string.
118
+ */
119
+ const H = generateH()
120
+
121
+ /**
122
+ * Generate the independent generator H using NUMS method for ed25519
123
+ *
124
+ * Uses a hash-and-check approach:
125
+ * 1. Hash domain||counter to get 32 bytes
126
+ * 2. Try to decode as an ed25519 point
127
+ * 3. Clear the cofactor by multiplying by 8
128
+ * 4. If valid and not identity/G, use it
129
+ */
130
+ function generateH(): typeof G {
131
+ let counter = 0
132
+
133
+ while (counter < 256) {
134
+ const input = new TextEncoder().encode(`${H_DOMAIN}:${counter}`)
135
+ const hashBytes = sha256(input)
136
+
137
+ try {
138
+ const rawPoint = ed25519.ExtendedPoint.fromHex(hashBytes)
139
+ const point = rawPoint.multiply(ED25519_COFACTOR)
140
+
141
+ if (!point.equals(ed25519.ExtendedPoint.ZERO)) {
142
+ const gBytes = G.toRawBytes()
143
+ const hBytes = point.toRawBytes()
144
+ if (bytesToHex(gBytes) !== bytesToHex(hBytes)) {
145
+ return point
146
+ }
147
+ }
148
+ } catch {
149
+ // Not a valid point encoding, try next counter
150
+ }
151
+
152
+ counter++
153
+ }
154
+
155
+ throw new CryptoError(
156
+ 'Failed to generate H point - this should never happen',
157
+ ErrorCode.CRYPTO_FAILED,
158
+ { context: { domain: H_DOMAIN } }
159
+ )
160
+ }
161
+
162
+ // ─── Utility Functions ────────────────────────────────────────────────────────
163
+
164
+ /**
165
+ * Convert bytes to bigint (little-endian)
166
+ */
167
+ function bytesToBigInt(bytes: Uint8Array): bigint {
168
+ let result = 0n
169
+ for (let i = bytes.length - 1; i >= 0; i--) {
170
+ result = result * 256n + BigInt(bytes[i])
171
+ }
172
+ return result
173
+ }
174
+
175
+ /**
176
+ * Convert bigint to bytes (little-endian)
177
+ */
178
+ function bigIntToBytes(n: bigint, length: number): Uint8Array {
179
+ const result = new Uint8Array(length)
180
+ let temp = n
181
+ for (let i = 0; i < length; i++) {
182
+ result[i] = Number(temp & 0xffn)
183
+ temp = temp >> 8n
184
+ }
185
+ return result
186
+ }
187
+
188
+ /**
189
+ * Convert hex string to bytes
190
+ */
191
+ function hexToBytes(hex: string): Uint8Array {
192
+ const result = new Uint8Array(hex.length / 2)
193
+ for (let i = 0; i < hex.length; i += 2) {
194
+ result[i / 2] = parseInt(hex.substring(i, i + 2), 16)
195
+ }
196
+ return result
197
+ }
198
+
199
+ // ─── Core Functions ───────────────────────────────────────────────────────────
200
+
201
+ /**
202
+ * Create a Pedersen commitment to a value (ed25519)
203
+ *
204
+ * C = v*G + r*H
205
+ *
206
+ * @param value - The value to commit to (must be < curve order)
207
+ * @param blinding - Optional blinding factor (random 32 bytes if not provided)
208
+ * @returns The commitment and blinding factor
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * // Commit to 1 NEAR (in yoctoNEAR)
213
+ * const { commitment, blinding } = commitNEAR(1_000_000_000_000_000_000_000_000n)
214
+ *
215
+ * // Verify the commitment
216
+ * const valid = verifyOpeningNEAR(commitment, 1_000_000_000_000_000_000_000_000n, blinding)
217
+ * ```
218
+ */
219
+ export function commitNEAR(
220
+ value: bigint,
221
+ blinding?: Uint8Array
222
+ ): NEARPedersenCommitment {
223
+ if (typeof value !== 'bigint') {
224
+ throw new ValidationError('must be a bigint', 'value', { received: typeof value })
225
+ }
226
+
227
+ if (value < 0n) {
228
+ throw new ValidationError('must be non-negative', 'value')
229
+ }
230
+
231
+ if (value >= ED25519_ORDER) {
232
+ throw new ValidationError(
233
+ 'must be less than curve order',
234
+ 'value',
235
+ { curveOrder: ED25519_ORDER.toString(16) }
236
+ )
237
+ }
238
+
239
+ const r = blinding ?? randomBytes(32)
240
+ if (r.length !== 32) {
241
+ throw new ValidationError('must be 32 bytes', 'blinding', { received: r.length })
242
+ }
243
+
244
+ const rScalar = bytesToBigInt(r) % ED25519_ORDER
245
+ if (rScalar === 0n) {
246
+ return commitNEAR(value, randomBytes(32))
247
+ }
248
+
249
+ let C: typeof G
250
+
251
+ if (value === 0n) {
252
+ C = H.multiply(rScalar)
253
+ } else {
254
+ const vG = G.multiply(value)
255
+ const rH = H.multiply(rScalar)
256
+ C = vG.add(rH)
257
+ }
258
+
259
+ const rScalarBytes = bigIntToBytes(rScalar, 32)
260
+
261
+ return {
262
+ commitment: `0x${bytesToHex(C.toRawBytes())}` as HexString,
263
+ blinding: `0x${bytesToHex(rScalarBytes)}` as HexString,
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Verify that a commitment opens to a specific value
269
+ *
270
+ * @param commitment - The commitment point to verify
271
+ * @param value - The claimed value
272
+ * @param blinding - The blinding factor used
273
+ * @returns true if the commitment opens correctly
274
+ */
275
+ export function verifyOpeningNEAR(
276
+ commitment: HexString,
277
+ value: bigint,
278
+ blinding: HexString
279
+ ): boolean {
280
+ try {
281
+ const commitmentBytes = hexToBytes(commitment.slice(2))
282
+ const C = ed25519.ExtendedPoint.fromHex(commitmentBytes)
283
+
284
+ const blindingBytes = hexToBytes(blinding.slice(2))
285
+ const rScalar = bytesToBigInt(blindingBytes) % ED25519_ORDER
286
+
287
+ let expected: typeof G
288
+
289
+ if (value === 0n) {
290
+ expected = H.multiply(rScalar)
291
+ } else if (rScalar === 0n) {
292
+ expected = G.multiply(value)
293
+ } else {
294
+ const vG = G.multiply(value)
295
+ const rH = H.multiply(rScalar)
296
+ expected = vG.add(rH)
297
+ }
298
+
299
+ return C.equals(expected)
300
+ } catch {
301
+ return false
302
+ }
303
+ }
304
+
305
+ // ─── NEP-141 Token Specific Functions ─────────────────────────────────────────
306
+
307
+ /**
308
+ * Create a commitment for a NEP-141 token amount
309
+ *
310
+ * Handles NEAR token decimals and u128 amount validation.
311
+ *
312
+ * @param amount - Token amount in smallest units (u128)
313
+ * @param tokenContract - NEP-141 token contract address
314
+ * @param decimals - Token decimals (e.g., 24 for NEAR, 6 for USDC)
315
+ * @returns NEP-141 token commitment with metadata
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * // Commit to 100 USDC (6 decimals)
320
+ * const commitment = commitNEP141Token(
321
+ * 100_000_000n, // 100 USDC in smallest units
322
+ * 'usdc.near',
323
+ * 6
324
+ * )
325
+ * ```
326
+ */
327
+ export function commitNEP141Token(
328
+ amount: bigint,
329
+ tokenContract: string,
330
+ decimals: number,
331
+ blinding?: Uint8Array
332
+ ): NEP141TokenCommitment {
333
+ if (amount < 0n || amount > MAX_NEAR_AMOUNT) {
334
+ throw new ValidationError(
335
+ 'NEP-141 token amount must be a valid u128 (0 to 2^128-1)',
336
+ 'amount',
337
+ { max: MAX_NEAR_AMOUNT.toString() }
338
+ )
339
+ }
340
+
341
+ // For amounts larger than curve order, we need to split
342
+ // However, for most practical purposes (total NEAR supply is ~1.1B * 10^24),
343
+ // we can commit directly as long as amount < ED25519_ORDER
344
+ if (amount >= ED25519_ORDER) {
345
+ throw new ValidationError(
346
+ 'Amount exceeds maximum committable value (curve order)',
347
+ 'amount',
348
+ { max: MAX_COMMITMENT_VALUE.toString() }
349
+ )
350
+ }
351
+
352
+ if (decimals < 0 || decimals > 24 || !Number.isInteger(decimals)) {
353
+ throw new ValidationError(
354
+ 'decimals must be an integer between 0 and 24',
355
+ 'decimals'
356
+ )
357
+ }
358
+
359
+ const { commitment, blinding: blindingHex } = commitNEAR(amount, blinding)
360
+
361
+ return {
362
+ commitment,
363
+ blinding: blindingHex,
364
+ tokenContract,
365
+ decimals,
366
+ amountRaw: amount,
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Verify a NEP-141 token commitment
372
+ *
373
+ * @param tokenCommitment - The NEP-141 token commitment to verify
374
+ * @param expectedAmount - The expected amount in smallest units
375
+ * @returns true if the commitment opens correctly
376
+ */
377
+ export function verifyNEP141TokenCommitment(
378
+ tokenCommitment: NEP141TokenCommitment,
379
+ expectedAmount: bigint
380
+ ): boolean {
381
+ return verifyOpeningNEAR(
382
+ tokenCommitment.commitment,
383
+ expectedAmount,
384
+ tokenCommitment.blinding
385
+ )
386
+ }
387
+
388
+ /**
389
+ * Convert human-readable token amount to smallest units
390
+ *
391
+ * @param amount - Human-readable amount (e.g., 100.5)
392
+ * @param decimals - Token decimals
393
+ * @returns Amount in smallest units as bigint
394
+ *
395
+ * @example
396
+ * ```typescript
397
+ * // 1 NEAR (24 decimals) = 10^24 yoctoNEAR
398
+ * const units = toYoctoNEAR(1, 24)
399
+ * // 1_000_000_000_000_000_000_000_000n
400
+ *
401
+ * // 100.5 USDC (6 decimals) = 100,500,000 units
402
+ * const usdc = toYoctoNEAR(100.5, 6)
403
+ * // 100_500_000n
404
+ * ```
405
+ */
406
+ export function toYoctoNEAR(amount: number | string, decimals: number): bigint {
407
+ const [whole, fraction = ''] = String(amount).split('.')
408
+ const paddedFraction = fraction.padEnd(decimals, '0').slice(0, decimals)
409
+ return BigInt(whole + paddedFraction)
410
+ }
411
+
412
+ /**
413
+ * Convert smallest units to human-readable amount
414
+ *
415
+ * @param amount - Amount in smallest units
416
+ * @param decimals - Token decimals
417
+ * @returns Human-readable string
418
+ *
419
+ * @example
420
+ * ```typescript
421
+ * // 1_000_000_000_000_000_000_000_000 yoctoNEAR = "1"
422
+ * const readable = fromYoctoNEAR(1_000_000_000_000_000_000_000_000n, 24)
423
+ * // "1"
424
+ * ```
425
+ */
426
+ export function fromYoctoNEAR(amount: bigint, decimals: number): string {
427
+ const str = amount.toString().padStart(decimals + 1, '0')
428
+ const whole = str.slice(0, -decimals) || '0'
429
+ const fraction = str.slice(-decimals).replace(/0+$/, '')
430
+ return fraction ? `${whole}.${fraction}` : whole
431
+ }
432
+
433
+ // ─── Homomorphic Operations ───────────────────────────────────────────────────
434
+
435
+ /**
436
+ * Add two commitments homomorphically (ed25519)
437
+ *
438
+ * C1 + C2 = (v1+v2)*G + (r1+r2)*H
439
+ *
440
+ * @param c1 - First commitment point
441
+ * @param c2 - Second commitment point
442
+ * @returns Sum of commitments
443
+ */
444
+ export function addCommitmentsNEAR(
445
+ c1: HexString,
446
+ c2: HexString
447
+ ): NEARCommitmentPoint {
448
+ if (!isValidHex(c1)) {
449
+ throw new ValidationError('must be a valid hex string', 'c1')
450
+ }
451
+ if (!isValidHex(c2)) {
452
+ throw new ValidationError('must be a valid hex string', 'c2')
453
+ }
454
+
455
+ let point1: typeof G
456
+ let point2: typeof G
457
+
458
+ try {
459
+ point1 = ed25519.ExtendedPoint.fromHex(hexToBytes(c1.slice(2)))
460
+ } catch {
461
+ throw new ValidationError('must be a valid ed25519 point', 'c1')
462
+ }
463
+ try {
464
+ point2 = ed25519.ExtendedPoint.fromHex(hexToBytes(c2.slice(2)))
465
+ } catch {
466
+ throw new ValidationError('must be a valid ed25519 point', 'c2')
467
+ }
468
+
469
+ const sum = point1.add(point2)
470
+
471
+ return {
472
+ commitment: `0x${bytesToHex(sum.toRawBytes())}` as HexString,
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Subtract two commitments homomorphically (ed25519)
478
+ *
479
+ * C1 - C2 = (v1-v2)*G + (r1-r2)*H
480
+ *
481
+ * @param c1 - First commitment point
482
+ * @param c2 - Second commitment point (to subtract)
483
+ * @returns Difference of commitments
484
+ */
485
+ export function subtractCommitmentsNEAR(
486
+ c1: HexString,
487
+ c2: HexString
488
+ ): NEARCommitmentPoint {
489
+ if (!isValidHex(c1)) {
490
+ throw new ValidationError('must be a valid hex string', 'c1')
491
+ }
492
+ if (!isValidHex(c2)) {
493
+ throw new ValidationError('must be a valid hex string', 'c2')
494
+ }
495
+
496
+ let point1: typeof G
497
+ let point2: typeof G
498
+
499
+ try {
500
+ point1 = ed25519.ExtendedPoint.fromHex(hexToBytes(c1.slice(2)))
501
+ } catch {
502
+ throw new ValidationError('must be a valid ed25519 point', 'c1')
503
+ }
504
+ try {
505
+ point2 = ed25519.ExtendedPoint.fromHex(hexToBytes(c2.slice(2)))
506
+ } catch {
507
+ throw new ValidationError('must be a valid ed25519 point', 'c2')
508
+ }
509
+
510
+ const diff = point1.subtract(point2)
511
+
512
+ if (diff.equals(ed25519.ExtendedPoint.ZERO)) {
513
+ return {
514
+ commitment: ('0x' + '00'.repeat(32)) as HexString,
515
+ }
516
+ }
517
+
518
+ return {
519
+ commitment: `0x${bytesToHex(diff.toRawBytes())}` as HexString,
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Add blinding factors (ed25519)
525
+ *
526
+ * @param b1 - First blinding factor
527
+ * @param b2 - Second blinding factor
528
+ * @returns Sum of blindings mod curve order
529
+ */
530
+ export function addBlindingsNEAR(b1: HexString, b2: HexString): HexString {
531
+ if (!isValidHex(b1)) {
532
+ throw new ValidationError('must be a valid hex string', 'b1')
533
+ }
534
+ if (!isValidHex(b2)) {
535
+ throw new ValidationError('must be a valid hex string', 'b2')
536
+ }
537
+
538
+ const b1Bytes = hexToBytes(b1.slice(2))
539
+ const b2Bytes = hexToBytes(b2.slice(2))
540
+
541
+ const b1Scalar = bytesToBigInt(b1Bytes)
542
+ const b2Scalar = bytesToBigInt(b2Bytes)
543
+
544
+ const sum = (b1Scalar + b2Scalar) % ED25519_ORDER
545
+ const sumBytes = bigIntToBytes(sum, 32)
546
+
547
+ return `0x${bytesToHex(sumBytes)}` as HexString
548
+ }
549
+
550
+ /**
551
+ * Subtract blinding factors (ed25519)
552
+ *
553
+ * @param b1 - First blinding factor
554
+ * @param b2 - Second blinding factor (to subtract)
555
+ * @returns Difference of blindings mod curve order
556
+ */
557
+ export function subtractBlindingsNEAR(b1: HexString, b2: HexString): HexString {
558
+ if (!isValidHex(b1)) {
559
+ throw new ValidationError('must be a valid hex string', 'b1')
560
+ }
561
+ if (!isValidHex(b2)) {
562
+ throw new ValidationError('must be a valid hex string', 'b2')
563
+ }
564
+
565
+ const b1Bytes = hexToBytes(b1.slice(2))
566
+ const b2Bytes = hexToBytes(b2.slice(2))
567
+
568
+ const b1Scalar = bytesToBigInt(b1Bytes)
569
+ const b2Scalar = bytesToBigInt(b2Bytes)
570
+
571
+ // Handle subtraction with modular arithmetic
572
+ const diff = (b1Scalar - b2Scalar + ED25519_ORDER) % ED25519_ORDER
573
+ const diffBytes = bigIntToBytes(diff, 32)
574
+
575
+ return `0x${bytesToHex(diffBytes)}` as HexString
576
+ }
577
+
578
+ // ─── Utility Functions ────────────────────────────────────────────────────────
579
+
580
+ /**
581
+ * Get the generators G and H for verification/debugging
582
+ *
583
+ * @returns The generator points as hex strings
584
+ */
585
+ export function getGeneratorsNEAR(): { G: HexString; H: HexString } {
586
+ return {
587
+ G: `0x${bytesToHex(G.toRawBytes())}` as HexString,
588
+ H: `0x${bytesToHex(H.toRawBytes())}` as HexString,
589
+ }
590
+ }
591
+
592
+ /**
593
+ * Generate a random blinding factor
594
+ *
595
+ * @returns Random 32-byte blinding factor as hex string
596
+ */
597
+ export function generateBlindingNEAR(): HexString {
598
+ const bytes = randomBytes(32)
599
+ const scalar = bytesToBigInt(bytes) % ED25519_ORDER
600
+
601
+ // Ensure non-zero
602
+ if (scalar === 0n) {
603
+ return generateBlindingNEAR()
604
+ }
605
+
606
+ const scalarBytes = bigIntToBytes(scalar, 32)
607
+ return `0x${bytesToHex(scalarBytes)}` as HexString
608
+ }