@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.
Files changed (262) 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 +48874 -18336
  7. package/dist/browser.mjs +674 -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-YWGJ77A2.mjs +33806 -0
  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-DXh2IGkz.d.ts +24681 -0
  24. package/dist/index-DeE1ZzA4.d.mts +24681 -0
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48676 -17318
  28. package/dist/index.mjs +583 -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 +276 -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 +201 -0
  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 +402 -0
  98. package/src/chains/solana/providers/index.ts +85 -0
  99. package/src/chains/solana/providers/interface.ts +221 -0
  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 +790 -0
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +170 -73
  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 +77 -7
  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 +37 -0
  116. package/src/compliance/range-sas.ts +956 -0
  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 +785 -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 +336 -0
  143. package/src/privacy-backends/interface.ts +906 -0
  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-types.ts +278 -0
  148. package/src/privacy-backends/privacycash.ts +456 -0
  149. package/src/privacy-backends/private-swap.ts +570 -0
  150. package/src/privacy-backends/rate-limiter.ts +683 -0
  151. package/src/privacy-backends/registry.ts +690 -0
  152. package/src/privacy-backends/router.ts +626 -0
  153. package/src/privacy-backends/shadowwire.ts +449 -0
  154. package/src/privacy-backends/sip-native.ts +256 -0
  155. package/src/privacy-logger.ts +191 -0
  156. package/src/production-safety.ts +373 -0
  157. package/src/proofs/aggregator.ts +1029 -0
  158. package/src/proofs/browser-composer.ts +1150 -0
  159. package/src/proofs/browser.ts +113 -25
  160. package/src/proofs/cache/index.ts +127 -0
  161. package/src/proofs/cache/interface.ts +545 -0
  162. package/src/proofs/cache/key-generator.ts +188 -0
  163. package/src/proofs/cache/lru-cache.ts +481 -0
  164. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  165. package/src/proofs/cache/persistent-cache.ts +788 -0
  166. package/src/proofs/compliance-proof.ts +872 -0
  167. package/src/proofs/composer/base.ts +923 -0
  168. package/src/proofs/composer/index.ts +25 -0
  169. package/src/proofs/composer/interface.ts +518 -0
  170. package/src/proofs/composer/types.ts +383 -0
  171. package/src/proofs/converters/halo2.ts +452 -0
  172. package/src/proofs/converters/index.ts +208 -0
  173. package/src/proofs/converters/interface.ts +363 -0
  174. package/src/proofs/converters/kimchi.ts +462 -0
  175. package/src/proofs/converters/noir.ts +451 -0
  176. package/src/proofs/fallback.ts +888 -0
  177. package/src/proofs/halo2.ts +42 -0
  178. package/src/proofs/index.ts +471 -0
  179. package/src/proofs/interface.ts +13 -0
  180. package/src/proofs/kimchi.ts +42 -0
  181. package/src/proofs/lazy.ts +1004 -0
  182. package/src/proofs/mock.ts +25 -1
  183. package/src/proofs/noir.ts +111 -30
  184. package/src/proofs/orchestrator.ts +960 -0
  185. package/src/proofs/parallel/concurrency.ts +297 -0
  186. package/src/proofs/parallel/dependency-graph.ts +602 -0
  187. package/src/proofs/parallel/executor.ts +420 -0
  188. package/src/proofs/parallel/index.ts +131 -0
  189. package/src/proofs/parallel/interface.ts +685 -0
  190. package/src/proofs/parallel/worker-pool.ts +644 -0
  191. package/src/proofs/providers/halo2.ts +560 -0
  192. package/src/proofs/providers/index.ts +34 -0
  193. package/src/proofs/providers/kimchi.ts +641 -0
  194. package/src/proofs/validator.ts +881 -0
  195. package/src/proofs/verifier.ts +867 -0
  196. package/src/quantum/index.ts +112 -0
  197. package/src/quantum/winternitz-vault.ts +639 -0
  198. package/src/quantum/wots.ts +611 -0
  199. package/src/settlement/backends/direct-chain.ts +1 -0
  200. package/src/settlement/index.ts +9 -0
  201. package/src/settlement/router.ts +732 -46
  202. package/src/solana/index.ts +72 -0
  203. package/src/solana/jito-relayer.ts +687 -0
  204. package/src/solana/noir-verifier-types.ts +430 -0
  205. package/src/solana/noir-verifier.ts +816 -0
  206. package/src/stealth/address-derivation.ts +193 -0
  207. package/src/stealth/ed25519.ts +431 -0
  208. package/src/stealth/index.ts +233 -0
  209. package/src/stealth/meta-address.ts +221 -0
  210. package/src/stealth/secp256k1.ts +368 -0
  211. package/src/stealth/utils.ts +194 -0
  212. package/src/stealth.ts +50 -1504
  213. package/src/surveillance/algorithms/address-reuse.ts +143 -0
  214. package/src/surveillance/algorithms/cluster.ts +247 -0
  215. package/src/surveillance/algorithms/exchange.ts +295 -0
  216. package/src/surveillance/algorithms/temporal.ts +337 -0
  217. package/src/surveillance/analyzer.ts +442 -0
  218. package/src/surveillance/index.ts +64 -0
  219. package/src/surveillance/scoring.ts +372 -0
  220. package/src/surveillance/types.ts +264 -0
  221. package/src/sync/index.ts +106 -0
  222. package/src/sync/manager.ts +504 -0
  223. package/src/sync/mock-provider.ts +318 -0
  224. package/src/sync/oblivious.ts +625 -0
  225. package/src/tokens/index.ts +15 -0
  226. package/src/tokens/registry.ts +301 -0
  227. package/src/utils/deprecation.ts +94 -0
  228. package/src/utils/index.ts +9 -0
  229. package/src/wallet/ethereum/index.ts +68 -0
  230. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  231. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  232. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  233. package/src/wallet/ethereum/types.ts +3 -1
  234. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  235. package/src/wallet/hardware/index.ts +10 -0
  236. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  237. package/src/wallet/index.ts +71 -0
  238. package/src/wallet/near/adapter.ts +626 -0
  239. package/src/wallet/near/index.ts +86 -0
  240. package/src/wallet/near/meteor-wallet.ts +1153 -0
  241. package/src/wallet/near/my-near-wallet.ts +790 -0
  242. package/src/wallet/near/wallet-selector.ts +702 -0
  243. package/src/wallet/solana/adapter.ts +6 -4
  244. package/src/wallet/solana/index.ts +13 -0
  245. package/src/wallet/solana/privacy-adapter.ts +567 -0
  246. package/src/wallet/sui/types.ts +6 -4
  247. package/src/zcash/rpc-client.ts +13 -6
  248. package/dist/chunk-3INS3PR5.mjs +0 -884
  249. package/dist/chunk-3OVABDRH.mjs +0 -17096
  250. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  251. package/dist/chunk-E6SZWREQ.mjs +0 -57
  252. package/dist/chunk-G33LB27A.mjs +0 -16166
  253. package/dist/chunk-HGU6HZRC.mjs +0 -231
  254. package/dist/chunk-L2K34JCU.mjs +0 -1496
  255. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  256. package/dist/constants-VOI7BSLK.mjs +0 -27
  257. package/dist/index-BYZbDjal.d.ts +0 -11390
  258. package/dist/index-CHB3KuOB.d.mts +0 -11859
  259. package/dist/index-CzWPI6Le.d.ts +0 -11859
  260. package/dist/index-xbWjohNq.d.mts +0 -11390
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-Q4NAVBTS.mjs +0 -46
@@ -0,0 +1,871 @@
1
+ /**
2
+ * NEAR Function Call Privacy Wrapper
3
+ *
4
+ * Privacy-preserving contract interactions using stealth accounts.
5
+ * Enables private DeFi, NFT, and smart contract interactions while
6
+ * hiding caller identity.
7
+ *
8
+ * @example Private contract call from stealth account
9
+ * ```typescript
10
+ * import { buildPrivateFunctionCall } from '@sip-protocol/sdk'
11
+ *
12
+ * const result = buildPrivateFunctionCall({
13
+ * contractId: 'dex.near',
14
+ * methodName: 'swap',
15
+ * args: { token_in: 'usdc.near', amount: '1000000' },
16
+ * deposit: ONE_NEAR,
17
+ * hideDeposit: true,
18
+ * })
19
+ * ```
20
+ *
21
+ * @example Private NFT mint
22
+ * ```typescript
23
+ * const result = buildPrivateNFTMint({
24
+ * contractId: 'nft.near',
25
+ * receiverMetaAddress: 'sip:near:0x...',
26
+ * tokenId: 'token-1',
27
+ * metadata: { title: 'My NFT' },
28
+ * })
29
+ * ```
30
+ *
31
+ * @packageDocumentation
32
+ */
33
+
34
+ import type { StealthAddress, StealthMetaAddress } from '@sip-protocol/types'
35
+ import { ValidationError } from '../../errors'
36
+ import { isValidAccountId, ONE_YOCTO } from './constants'
37
+ import { generateNEARStealthAddress, parseNEARStealthMetaAddress } from './stealth'
38
+ import { createAnnouncementMemo } from './types'
39
+ import { commitNEAR, type NEARPedersenCommitment } from './commitment'
40
+ import type {
41
+ NEARAction,
42
+ NEARFunctionCallAction,
43
+ NEARAddKeyAction,
44
+ } from './implicit-account'
45
+
46
+ // ─── Types ────────────────────────────────────────────────────────────────────
47
+
48
+ /**
49
+ * Parameters for a private function call
50
+ */
51
+ export interface PrivateFunctionCallParams {
52
+ /** Contract to call */
53
+ contractId: string
54
+ /** Method name to invoke */
55
+ methodName: string
56
+ /** Method arguments (will be JSON stringified) */
57
+ args?: Record<string, unknown>
58
+ /** NEAR deposit to attach (default: 0) */
59
+ deposit?: bigint
60
+ /** Gas to attach (default: DEFAULT_GAS) */
61
+ gas?: bigint
62
+ /** Hide deposit amount with commitment */
63
+ hideDeposit?: boolean
64
+ }
65
+
66
+ /**
67
+ * Result of building a private function call
68
+ */
69
+ export interface PrivateFunctionCallResult {
70
+ /** Transaction actions */
71
+ actions: NEARAction[]
72
+ /** Receiver ID (the contract) */
73
+ receiverId: string
74
+ /** Deposit commitment (if hideDeposit is true) */
75
+ depositCommitment?: NEARPedersenCommitment
76
+ /** Gas attached */
77
+ gasAttached: bigint
78
+ /** Deposit attached */
79
+ depositAttached: bigint
80
+ }
81
+
82
+ /**
83
+ * Parameters for a private function call from a stealth account
84
+ */
85
+ export interface PrivateFunctionCallFromStealthParams extends PrivateFunctionCallParams {
86
+ /** Stealth account ID to call from */
87
+ stealthAccountId: string
88
+ }
89
+
90
+ /**
91
+ * Parameters for building a multi-step private transaction
92
+ */
93
+ export interface MultiStepPrivateTransactionParams {
94
+ /** Steps to execute in order */
95
+ steps: Array<{
96
+ /** Contract to call */
97
+ contractId: string
98
+ /** Method name */
99
+ methodName: string
100
+ /** Method arguments */
101
+ args?: Record<string, unknown>
102
+ /** Deposit for this step */
103
+ deposit?: bigint
104
+ /** Gas for this step */
105
+ gas?: bigint
106
+ }>
107
+ /** Total gas budget for all steps */
108
+ totalGas?: bigint
109
+ }
110
+
111
+ /**
112
+ * Result of building a multi-step private transaction
113
+ */
114
+ export interface MultiStepPrivateTransactionResult {
115
+ /** Individual step builds */
116
+ steps: Array<{
117
+ actions: NEARAction[]
118
+ receiverId: string
119
+ deposit: bigint
120
+ gas: bigint
121
+ }>
122
+ /** Total deposit across all steps */
123
+ totalDeposit: bigint
124
+ /** Total gas across all steps */
125
+ totalGas: bigint
126
+ }
127
+
128
+ /**
129
+ * Parameters for function call access key
130
+ */
131
+ export interface FunctionCallAccessKeyParams {
132
+ /** Public key to add (ed25519:base58 format) */
133
+ publicKey: string
134
+ /** Contract the key can call */
135
+ receiverId: string
136
+ /** Methods the key can call (empty = all methods) */
137
+ methodNames: string[]
138
+ /** Allowance in yoctoNEAR (optional) */
139
+ allowance?: bigint
140
+ }
141
+
142
+ /**
143
+ * Parameters for private NFT mint
144
+ */
145
+ export interface PrivateNFTMintParams {
146
+ /** NFT contract address */
147
+ contractId: string
148
+ /** Recipient's stealth meta-address */
149
+ receiverMetaAddress: StealthMetaAddress | string
150
+ /** Token ID */
151
+ tokenId: string
152
+ /** Token metadata */
153
+ metadata?: {
154
+ title?: string
155
+ description?: string
156
+ media?: string
157
+ copies?: number
158
+ }
159
+ /** Deposit for storage (default: 0.1 NEAR) */
160
+ deposit?: bigint
161
+ }
162
+
163
+ /**
164
+ * Result of building a private NFT mint
165
+ */
166
+ export interface PrivateNFTMintResult {
167
+ /** Transaction actions */
168
+ actions: NEARAction[]
169
+ /** NFT contract address */
170
+ receiverId: string
171
+ /** Stealth address receiving the NFT */
172
+ stealthAddress: StealthAddress
173
+ /** NEAR implicit account ID */
174
+ stealthAccountId: string
175
+ /** Announcement memo */
176
+ announcementMemo: string
177
+ }
178
+
179
+ /**
180
+ * Parameters for private DeFi swap
181
+ */
182
+ export interface PrivateDeFiSwapParams {
183
+ /** DEX contract address */
184
+ dexContract: string
185
+ /** Token to swap from */
186
+ tokenIn: string
187
+ /** Token to swap to */
188
+ tokenOut: string
189
+ /** Amount to swap (in smallest units) */
190
+ amountIn: bigint
191
+ /** Minimum amount to receive */
192
+ minAmountOut: bigint
193
+ /** Recipient's stealth meta-address for output */
194
+ receiverMetaAddress: StealthMetaAddress | string
195
+ /** Slippage tolerance (default: 0.5%) */
196
+ slippageBps?: number
197
+ }
198
+
199
+ /**
200
+ * Result of building a private DeFi swap
201
+ */
202
+ export interface PrivateDeFiSwapResult {
203
+ /** Transaction actions */
204
+ actions: NEARAction[]
205
+ /** DEX contract address */
206
+ receiverId: string
207
+ /** Stealth address receiving swap output */
208
+ stealthAddress: StealthAddress
209
+ /** NEAR implicit account ID */
210
+ stealthAccountId: string
211
+ /** Announcement memo */
212
+ announcementMemo: string
213
+ /** Expected output amount */
214
+ expectedOutput: bigint
215
+ }
216
+
217
+ // ─── Constants ────────────────────────────────────────────────────────────────
218
+
219
+ /**
220
+ * Default gas for function calls (30 TGas)
221
+ */
222
+ export const FUNCTION_CALL_DEFAULT_GAS = 30_000_000_000_000n
223
+
224
+ /**
225
+ * Gas for NFT mint operations (50 TGas)
226
+ */
227
+ export const NFT_MINT_GAS = 50_000_000_000_000n
228
+
229
+ /**
230
+ * Default deposit for NFT storage (0.1 NEAR)
231
+ */
232
+ export const NFT_STORAGE_DEPOSIT = 100_000_000_000_000_000_000_000n
233
+
234
+ /**
235
+ * Gas for DEX swap operations (100 TGas)
236
+ */
237
+ export const DEX_SWAP_GAS = 100_000_000_000_000n
238
+
239
+ // ─── Private Function Calls ───────────────────────────────────────────────────
240
+
241
+ /**
242
+ * Build a private function call
243
+ *
244
+ * Creates a function call action that can be executed from a stealth account,
245
+ * optionally hiding the deposit amount with a Pedersen commitment.
246
+ *
247
+ * @param params - Function call parameters
248
+ * @returns Function call build
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * const result = buildPrivateFunctionCall({
253
+ * contractId: 'dex.near',
254
+ * methodName: 'swap',
255
+ * args: { token_in: 'usdc.near', amount: '1000000' },
256
+ * deposit: ONE_NEAR,
257
+ * hideDeposit: true,
258
+ * })
259
+ * ```
260
+ */
261
+ export function buildPrivateFunctionCall(
262
+ params: PrivateFunctionCallParams
263
+ ): PrivateFunctionCallResult {
264
+ const {
265
+ contractId,
266
+ methodName,
267
+ args = {},
268
+ deposit = 0n,
269
+ gas = FUNCTION_CALL_DEFAULT_GAS,
270
+ hideDeposit = false,
271
+ } = params
272
+
273
+ // Validate contract ID
274
+ if (!isValidAccountId(contractId)) {
275
+ throw new ValidationError('Invalid contractId', 'contractId')
276
+ }
277
+
278
+ // Validate method name
279
+ if (!methodName || methodName.length === 0) {
280
+ throw new ValidationError('methodName is required', 'methodName')
281
+ }
282
+
283
+ // Validate gas
284
+ if (gas <= 0n) {
285
+ throw new ValidationError('gas must be greater than 0', 'gas')
286
+ }
287
+
288
+ // Validate deposit
289
+ if (deposit < 0n) {
290
+ throw new ValidationError('deposit cannot be negative', 'deposit')
291
+ }
292
+
293
+ // Create deposit commitment if requested
294
+ let depositCommitment: NEARPedersenCommitment | undefined
295
+ if (hideDeposit && deposit > 0n) {
296
+ depositCommitment = commitNEAR(deposit)
297
+ }
298
+
299
+ // Build function call args
300
+ const argsString = JSON.stringify(args)
301
+
302
+ // Build function call action
303
+ const actions: NEARAction[] = [
304
+ {
305
+ type: 'FunctionCall',
306
+ params: {
307
+ methodName,
308
+ args: argsString,
309
+ gas,
310
+ deposit,
311
+ } as NEARFunctionCallAction,
312
+ },
313
+ ]
314
+
315
+ return {
316
+ actions,
317
+ receiverId: contractId,
318
+ depositCommitment,
319
+ gasAttached: gas,
320
+ depositAttached: deposit,
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Build a batch of private function calls
326
+ *
327
+ * Creates multiple function call actions for a single transaction.
328
+ * All calls are to the same contract.
329
+ *
330
+ * @param contractId - Contract to call
331
+ * @param calls - List of method calls
332
+ * @returns Batch function call build
333
+ */
334
+ export function buildBatchPrivateFunctionCalls(
335
+ contractId: string,
336
+ calls: Array<{
337
+ methodName: string
338
+ args?: Record<string, unknown>
339
+ deposit?: bigint
340
+ gas?: bigint
341
+ }>
342
+ ): PrivateFunctionCallResult {
343
+ if (!isValidAccountId(contractId)) {
344
+ throw new ValidationError('Invalid contractId', 'contractId')
345
+ }
346
+
347
+ if (!calls || calls.length === 0) {
348
+ throw new ValidationError('At least one call is required', 'calls')
349
+ }
350
+
351
+ if (calls.length > 10) {
352
+ throw new ValidationError('Maximum 10 calls per batch', 'calls')
353
+ }
354
+
355
+ const actions: NEARAction[] = []
356
+ let totalDeposit = 0n
357
+ let totalGas = 0n
358
+
359
+ for (const call of calls) {
360
+ const {
361
+ methodName,
362
+ args = {},
363
+ deposit = 0n,
364
+ gas = FUNCTION_CALL_DEFAULT_GAS,
365
+ } = call
366
+
367
+ if (!methodName || methodName.length === 0) {
368
+ throw new ValidationError('methodName is required for each call', 'calls')
369
+ }
370
+
371
+ actions.push({
372
+ type: 'FunctionCall',
373
+ params: {
374
+ methodName,
375
+ args: JSON.stringify(args),
376
+ gas,
377
+ deposit,
378
+ } as NEARFunctionCallAction,
379
+ })
380
+
381
+ totalDeposit += deposit
382
+ totalGas += gas
383
+ }
384
+
385
+ return {
386
+ actions,
387
+ receiverId: contractId,
388
+ gasAttached: totalGas,
389
+ depositAttached: totalDeposit,
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Build a multi-step private transaction
395
+ *
396
+ * For transactions that need to call multiple contracts in sequence.
397
+ * Returns separate transaction builds for each step.
398
+ *
399
+ * @param params - Multi-step transaction parameters
400
+ * @returns Multi-step transaction build
401
+ */
402
+ export function buildMultiStepPrivateTransaction(
403
+ params: MultiStepPrivateTransactionParams
404
+ ): MultiStepPrivateTransactionResult {
405
+ const { steps, totalGas } = params
406
+
407
+ if (!steps || steps.length === 0) {
408
+ throw new ValidationError('At least one step is required', 'steps')
409
+ }
410
+
411
+ if (steps.length > 10) {
412
+ throw new ValidationError('Maximum 10 steps per transaction', 'steps')
413
+ }
414
+
415
+ const results: MultiStepPrivateTransactionResult['steps'] = []
416
+ let totalDeposit = 0n
417
+ let calculatedTotalGas = 0n
418
+
419
+ // Calculate gas per step if total is specified
420
+ const gasPerStep = totalGas
421
+ ? totalGas / BigInt(steps.length)
422
+ : undefined
423
+
424
+ for (const step of steps) {
425
+ const {
426
+ contractId,
427
+ methodName,
428
+ args = {},
429
+ deposit = 0n,
430
+ gas = gasPerStep ?? FUNCTION_CALL_DEFAULT_GAS,
431
+ } = step
432
+
433
+ if (!isValidAccountId(contractId)) {
434
+ throw new ValidationError(`Invalid contractId: ${contractId}`, 'steps')
435
+ }
436
+
437
+ if (!methodName || methodName.length === 0) {
438
+ throw new ValidationError('methodName is required for each step', 'steps')
439
+ }
440
+
441
+ const actions: NEARAction[] = [
442
+ {
443
+ type: 'FunctionCall',
444
+ params: {
445
+ methodName,
446
+ args: JSON.stringify(args),
447
+ gas,
448
+ deposit,
449
+ } as NEARFunctionCallAction,
450
+ },
451
+ ]
452
+
453
+ results.push({
454
+ actions,
455
+ receiverId: contractId,
456
+ deposit,
457
+ gas,
458
+ })
459
+
460
+ totalDeposit += deposit
461
+ calculatedTotalGas += gas
462
+ }
463
+
464
+ return {
465
+ steps: results,
466
+ totalDeposit,
467
+ totalGas: calculatedTotalGas,
468
+ }
469
+ }
470
+
471
+ // ─── Access Key Management ────────────────────────────────────────────────────
472
+
473
+ /**
474
+ * Build function call access key for a stealth account
475
+ *
476
+ * Allows adding a limited access key to a stealth account that can
477
+ * only call specific methods on a specific contract.
478
+ *
479
+ * @param params - Access key parameters
480
+ * @returns Add key action
481
+ *
482
+ * @example
483
+ * ```typescript
484
+ * const action = buildFunctionCallAccessKey({
485
+ * publicKey: 'ed25519:...',
486
+ * receiverId: 'dex.near',
487
+ * methodNames: ['swap', 'deposit', 'withdraw'],
488
+ * allowance: ONE_NEAR,
489
+ * })
490
+ * ```
491
+ */
492
+ export function buildFunctionCallAccessKey(
493
+ params: FunctionCallAccessKeyParams
494
+ ): NEARAction {
495
+ const {
496
+ publicKey,
497
+ receiverId,
498
+ methodNames,
499
+ allowance,
500
+ } = params
501
+
502
+ // Validate public key format
503
+ if (!publicKey.startsWith('ed25519:')) {
504
+ throw new ValidationError(
505
+ 'publicKey must be in ed25519:base58 format',
506
+ 'publicKey'
507
+ )
508
+ }
509
+
510
+ // Validate receiver
511
+ if (!isValidAccountId(receiverId)) {
512
+ throw new ValidationError('Invalid receiverId', 'receiverId')
513
+ }
514
+
515
+ return {
516
+ type: 'AddKey',
517
+ params: {
518
+ publicKey,
519
+ accessKey: {
520
+ permission: {
521
+ FunctionCall: {
522
+ allowance,
523
+ receiverId,
524
+ methodNames,
525
+ },
526
+ },
527
+ },
528
+ } as NEARAddKeyAction,
529
+ }
530
+ }
531
+
532
+ // ─── NFT Privacy ──────────────────────────────────────────────────────────────
533
+
534
+ /**
535
+ * Build a private NFT mint
536
+ *
537
+ * Mints an NFT to a stealth address, hiding the recipient's identity.
538
+ *
539
+ * @param params - NFT mint parameters
540
+ * @returns NFT mint build
541
+ *
542
+ * @example
543
+ * ```typescript
544
+ * const result = buildPrivateNFTMint({
545
+ * contractId: 'nft.near',
546
+ * receiverMetaAddress: 'sip:near:0x...',
547
+ * tokenId: 'token-1',
548
+ * metadata: { title: 'Private NFT' },
549
+ * })
550
+ * ```
551
+ */
552
+ export function buildPrivateNFTMint(
553
+ params: PrivateNFTMintParams
554
+ ): PrivateNFTMintResult {
555
+ const {
556
+ contractId,
557
+ receiverMetaAddress,
558
+ tokenId,
559
+ metadata = {},
560
+ deposit = NFT_STORAGE_DEPOSIT,
561
+ } = params
562
+
563
+ // Validate contract
564
+ if (!isValidAccountId(contractId)) {
565
+ throw new ValidationError('Invalid NFT contractId', 'contractId')
566
+ }
567
+
568
+ // Parse meta-address if string
569
+ const metaAddr = typeof receiverMetaAddress === 'string'
570
+ ? parseNEARStealthMetaAddress(receiverMetaAddress)
571
+ : receiverMetaAddress
572
+
573
+ // Validate chain
574
+ if (metaAddr.chain !== 'near') {
575
+ throw new ValidationError(
576
+ `Expected NEAR meta-address, got chain '${metaAddr.chain}'`,
577
+ 'receiverMetaAddress'
578
+ )
579
+ }
580
+
581
+ // Generate stealth address for receiver
582
+ const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(metaAddr)
583
+
584
+ // Create announcement memo
585
+ const announcementMemo = createAnnouncementMemo(
586
+ stealthAddress.ephemeralPublicKey,
587
+ stealthAddress.viewTag
588
+ )
589
+
590
+ // Build NFT mint args (NEP-171 standard)
591
+ const args = {
592
+ token_id: tokenId,
593
+ receiver_id: implicitAccountId,
594
+ token_metadata: {
595
+ title: metadata.title,
596
+ description: metadata.description,
597
+ media: metadata.media,
598
+ copies: metadata.copies,
599
+ },
600
+ memo: announcementMemo,
601
+ }
602
+
603
+ // Build mint action
604
+ const actions: NEARAction[] = [
605
+ {
606
+ type: 'FunctionCall',
607
+ params: {
608
+ methodName: 'nft_mint',
609
+ args: JSON.stringify(args),
610
+ gas: NFT_MINT_GAS,
611
+ deposit,
612
+ } as NEARFunctionCallAction,
613
+ },
614
+ ]
615
+
616
+ return {
617
+ actions,
618
+ receiverId: contractId,
619
+ stealthAddress,
620
+ stealthAccountId: implicitAccountId,
621
+ announcementMemo,
622
+ }
623
+ }
624
+
625
+ /**
626
+ * Build a private NFT transfer
627
+ *
628
+ * Transfers an NFT to a stealth address.
629
+ *
630
+ * @param contractId - NFT contract address
631
+ * @param tokenId - Token ID to transfer
632
+ * @param receiverMetaAddress - Recipient's stealth meta-address
633
+ * @returns NFT transfer build
634
+ */
635
+ export function buildPrivateNFTTransfer(
636
+ contractId: string,
637
+ tokenId: string,
638
+ receiverMetaAddress: StealthMetaAddress | string
639
+ ): PrivateNFTMintResult {
640
+ // Validate contract
641
+ if (!isValidAccountId(contractId)) {
642
+ throw new ValidationError('Invalid NFT contractId', 'contractId')
643
+ }
644
+
645
+ // Parse meta-address if string
646
+ const metaAddr = typeof receiverMetaAddress === 'string'
647
+ ? parseNEARStealthMetaAddress(receiverMetaAddress)
648
+ : receiverMetaAddress
649
+
650
+ // Validate chain
651
+ if (metaAddr.chain !== 'near') {
652
+ throw new ValidationError(
653
+ `Expected NEAR meta-address, got chain '${metaAddr.chain}'`,
654
+ 'receiverMetaAddress'
655
+ )
656
+ }
657
+
658
+ // Generate stealth address for receiver
659
+ const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(metaAddr)
660
+
661
+ // Create announcement memo
662
+ const announcementMemo = createAnnouncementMemo(
663
+ stealthAddress.ephemeralPublicKey,
664
+ stealthAddress.viewTag
665
+ )
666
+
667
+ // Build NFT transfer args (NEP-171 standard)
668
+ const args = {
669
+ token_id: tokenId,
670
+ receiver_id: implicitAccountId,
671
+ memo: announcementMemo,
672
+ }
673
+
674
+ // Build transfer action
675
+ const actions: NEARAction[] = [
676
+ {
677
+ type: 'FunctionCall',
678
+ params: {
679
+ methodName: 'nft_transfer',
680
+ args: JSON.stringify(args),
681
+ gas: NFT_MINT_GAS,
682
+ deposit: ONE_YOCTO, // NEP-171 requires 1 yoctoNEAR
683
+ } as NEARFunctionCallAction,
684
+ },
685
+ ]
686
+
687
+ return {
688
+ actions,
689
+ receiverId: contractId,
690
+ stealthAddress,
691
+ stealthAccountId: implicitAccountId,
692
+ announcementMemo,
693
+ }
694
+ }
695
+
696
+ // ─── DeFi Privacy ─────────────────────────────────────────────────────────────
697
+
698
+ /**
699
+ * Build a private DeFi swap
700
+ *
701
+ * Executes a token swap with output going to a stealth address.
702
+ *
703
+ * @param params - DeFi swap parameters
704
+ * @returns DeFi swap build
705
+ *
706
+ * @example
707
+ * ```typescript
708
+ * const result = buildPrivateDeFiSwap({
709
+ * dexContract: 'ref-finance.near',
710
+ * tokenIn: 'usdc.near',
711
+ * tokenOut: 'wrap.near',
712
+ * amountIn: 1000_000_000n, // 1000 USDC
713
+ * minAmountOut: 900_000_000_000_000_000_000_000n, // min 0.9 NEAR
714
+ * receiverMetaAddress: 'sip:near:0x...',
715
+ * })
716
+ * ```
717
+ */
718
+ export function buildPrivateDeFiSwap(
719
+ params: PrivateDeFiSwapParams
720
+ ): PrivateDeFiSwapResult {
721
+ const {
722
+ dexContract,
723
+ tokenIn,
724
+ tokenOut,
725
+ amountIn,
726
+ minAmountOut,
727
+ receiverMetaAddress,
728
+ slippageBps = 50, // 0.5% default
729
+ } = params
730
+
731
+ // Validate DEX contract
732
+ if (!isValidAccountId(dexContract)) {
733
+ throw new ValidationError('Invalid dexContract', 'dexContract')
734
+ }
735
+
736
+ // Validate tokens
737
+ if (!isValidAccountId(tokenIn)) {
738
+ throw new ValidationError('Invalid tokenIn', 'tokenIn')
739
+ }
740
+ if (!isValidAccountId(tokenOut)) {
741
+ throw new ValidationError('Invalid tokenOut', 'tokenOut')
742
+ }
743
+
744
+ // Validate amounts
745
+ if (amountIn <= 0n) {
746
+ throw new ValidationError('amountIn must be greater than 0', 'amountIn')
747
+ }
748
+ if (minAmountOut <= 0n) {
749
+ throw new ValidationError('minAmountOut must be greater than 0', 'minAmountOut')
750
+ }
751
+
752
+ // Parse meta-address if string
753
+ const metaAddr = typeof receiverMetaAddress === 'string'
754
+ ? parseNEARStealthMetaAddress(receiverMetaAddress)
755
+ : receiverMetaAddress
756
+
757
+ // Validate chain
758
+ if (metaAddr.chain !== 'near') {
759
+ throw new ValidationError(
760
+ `Expected NEAR meta-address, got chain '${metaAddr.chain}'`,
761
+ 'receiverMetaAddress'
762
+ )
763
+ }
764
+
765
+ // Generate stealth address for swap output
766
+ const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(metaAddr)
767
+
768
+ // Create announcement memo
769
+ const announcementMemo = createAnnouncementMemo(
770
+ stealthAddress.ephemeralPublicKey,
771
+ stealthAddress.viewTag
772
+ )
773
+
774
+ // Calculate expected output with slippage
775
+ const slippageMultiplier = 10000n - BigInt(slippageBps)
776
+ const expectedOutput = (minAmountOut * 10000n) / slippageMultiplier
777
+
778
+ // Build swap message for ft_transfer_call
779
+ const swapMsg = JSON.stringify({
780
+ actions: [
781
+ {
782
+ pool_id: 0, // Would need actual pool ID
783
+ token_in: tokenIn,
784
+ token_out: tokenOut,
785
+ amount_in: amountIn.toString(),
786
+ min_amount_out: minAmountOut.toString(),
787
+ },
788
+ ],
789
+ receiver_id: implicitAccountId,
790
+ })
791
+
792
+ // Build ft_transfer_call action (to be sent to tokenIn contract)
793
+ const args = {
794
+ receiver_id: dexContract,
795
+ amount: amountIn.toString(),
796
+ msg: swapMsg,
797
+ memo: announcementMemo,
798
+ }
799
+
800
+ const actions: NEARAction[] = [
801
+ {
802
+ type: 'FunctionCall',
803
+ params: {
804
+ methodName: 'ft_transfer_call',
805
+ args: JSON.stringify(args),
806
+ gas: DEX_SWAP_GAS,
807
+ deposit: ONE_YOCTO,
808
+ } as NEARFunctionCallAction,
809
+ },
810
+ ]
811
+
812
+ return {
813
+ actions,
814
+ receiverId: tokenIn, // Call goes to token contract
815
+ stealthAddress,
816
+ stealthAccountId: implicitAccountId,
817
+ announcementMemo,
818
+ expectedOutput,
819
+ }
820
+ }
821
+
822
+ // ─── Gas Estimation ───────────────────────────────────────────────────────────
823
+
824
+ /**
825
+ * Estimate gas for a function call
826
+ *
827
+ * @param methodName - Method being called
828
+ * @param argsSize - Size of args in bytes
829
+ * @returns Estimated gas in yoctoNEAR
830
+ */
831
+ export function estimateFunctionCallGas(
832
+ methodName: string,
833
+ argsSize: number = 0
834
+ ): bigint {
835
+ // Base gas for function call
836
+ let gas = 5_000_000_000_000n // 5 TGas base
837
+
838
+ // Add gas for args serialization
839
+ gas += BigInt(argsSize) * 1_000_000_000n // 1 GGas per byte
840
+
841
+ // Add method-specific gas estimates
842
+ if (methodName === 'ft_transfer' || methodName === 'ft_transfer_call') {
843
+ gas += 10_000_000_000_000n // +10 TGas
844
+ } else if (methodName === 'nft_mint' || methodName === 'nft_transfer') {
845
+ gas += 20_000_000_000_000n // +20 TGas
846
+ } else if (methodName.includes('swap')) {
847
+ gas += 50_000_000_000_000n // +50 TGas for swaps
848
+ }
849
+
850
+ // Cap at reasonable maximum
851
+ const maxGas = 300_000_000_000_000n // 300 TGas
852
+ return gas > maxGas ? maxGas : gas
853
+ }
854
+
855
+ /**
856
+ * Estimate total gas for a multi-step transaction
857
+ *
858
+ * @param steps - Transaction steps
859
+ * @returns Total estimated gas
860
+ */
861
+ export function estimateMultiStepGas(
862
+ steps: Array<{ methodName: string; argsSize?: number }>
863
+ ): bigint {
864
+ let total = 0n
865
+
866
+ for (const step of steps) {
867
+ total += estimateFunctionCallGas(step.methodName, step.argsSize ?? 0)
868
+ }
869
+
870
+ return total
871
+ }