@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,654 @@
1
+ /**
2
+ * NEAR Privacy Transaction History
3
+ *
4
+ * Provides transaction history retrieval for NEAR privacy operations,
5
+ * including stealth address resolution, amount revelation, and filtering.
6
+ *
7
+ * ## Features
8
+ *
9
+ * - Historical transaction scanning with pagination
10
+ * - Amount decryption for owned transactions via viewing key
11
+ * - Transaction type classification (send, receive, contract_call)
12
+ * - Filtering by date range, type, token
13
+ * - Search by transaction hash or address
14
+ * - Export to CSV/JSON formats
15
+ *
16
+ * @module chains/near/history
17
+ */
18
+
19
+ import type { HexString } from '@sip-protocol/types'
20
+ import { ValidationError } from '../../errors'
21
+ import { isValidHex } from '../../validation'
22
+ import {
23
+ createNEARStealthScanner,
24
+ type NEARDetectedPaymentResult,
25
+ } from './resolver'
26
+ import { getExplorerUrl } from './constants'
27
+
28
+ // ─── Types ────────────────────────────────────────────────────────────────────
29
+
30
+ /**
31
+ * Transaction type classification
32
+ */
33
+ export type NEARTransactionType = 'send' | 'receive' | 'contract_call'
34
+
35
+ /**
36
+ * Privacy level indicator
37
+ */
38
+ export type NEARHistoryPrivacyLevel = 'transparent' | 'shielded' | 'compliant'
39
+
40
+ /**
41
+ * A historical transaction with privacy metadata
42
+ */
43
+ export interface NEARHistoricalTransaction {
44
+ /** Unique transaction hash */
45
+ hash: string
46
+
47
+ /** Transaction timestamp (milliseconds since epoch) */
48
+ timestamp: number
49
+
50
+ /** Block height */
51
+ blockHeight: number
52
+
53
+ /** Transaction type */
54
+ type: NEARTransactionType
55
+
56
+ /** Stealth address (implicit account ID) */
57
+ stealthAddress: string
58
+
59
+ /** Stealth public key (hex) */
60
+ stealthPublicKey: HexString
61
+
62
+ /** Ephemeral public key from sender (hex) */
63
+ ephemeralPublicKey: HexString
64
+
65
+ /** View tag for efficient scanning */
66
+ viewTag: number
67
+
68
+ /** Amount in smallest units (yoctoNEAR or token units) */
69
+ amount: string
70
+
71
+ /** Human-readable amount (with decimals applied) */
72
+ amountFormatted: string
73
+
74
+ /** Token symbol or 'NEAR' */
75
+ token: string
76
+
77
+ /** Token contract address (null for native NEAR) */
78
+ tokenContract: string | null
79
+
80
+ /** Token decimals */
81
+ decimals: number
82
+
83
+ /** Privacy level used */
84
+ privacyLevel: NEARHistoryPrivacyLevel
85
+
86
+ /** Whether the amount was revealed via viewing key */
87
+ amountRevealed: boolean
88
+
89
+ /** Sender account (if known) */
90
+ sender?: string
91
+
92
+ /** Receiver account (if known) */
93
+ receiver?: string
94
+
95
+ /** Transaction fee in yoctoNEAR */
96
+ fee?: string
97
+
98
+ /** Block explorer URL */
99
+ explorerUrl: string
100
+
101
+ /** Label for this recipient (if multiple viewing keys) */
102
+ recipientLabel?: string
103
+ }
104
+
105
+ /**
106
+ * Parameters for retrieving transaction history
107
+ */
108
+ export interface NEARTransactionHistoryParams {
109
+ /** NEAR RPC URL */
110
+ rpcUrl: string
111
+
112
+ /** Viewing private key for scanning (hex) */
113
+ viewingPrivateKey: HexString
114
+
115
+ /** Spending private key for address verification (hex) */
116
+ spendingPrivateKey: HexString
117
+
118
+ /** Network type */
119
+ network?: 'mainnet' | 'testnet'
120
+
121
+ /** Start block height (optional) */
122
+ fromBlock?: number
123
+
124
+ /** End block height (optional) */
125
+ toBlock?: number
126
+
127
+ /** Start timestamp filter (milliseconds) */
128
+ fromTimestamp?: number
129
+
130
+ /** End timestamp filter (milliseconds) */
131
+ toTimestamp?: number
132
+
133
+ /** Maximum transactions to return */
134
+ limit?: number
135
+
136
+ /** Pagination cursor */
137
+ cursor?: string
138
+
139
+ /** Filter by transaction types */
140
+ typeFilter?: NEARTransactionType[]
141
+
142
+ /** Filter by token contracts (null = native NEAR) */
143
+ tokenFilter?: (string | null)[]
144
+
145
+ /** Search by transaction hash or address */
146
+ searchQuery?: string
147
+
148
+ /** Request timeout in milliseconds */
149
+ timeout?: number
150
+ }
151
+
152
+ /**
153
+ * Result of transaction history retrieval
154
+ */
155
+ export interface NEARTransactionHistoryResult {
156
+ /** Retrieved transactions */
157
+ transactions: NEARHistoricalTransaction[]
158
+
159
+ /** Total transactions found (before filtering) */
160
+ totalCount: number
161
+
162
+ /** Whether more results are available */
163
+ hasMore: boolean
164
+
165
+ /** Cursor for next page */
166
+ nextCursor?: string
167
+
168
+ /** Last block height scanned */
169
+ lastBlockHeight?: number
170
+
171
+ /** Time taken in milliseconds */
172
+ scanTimeMs: number
173
+ }
174
+
175
+ /**
176
+ * Export format options
177
+ */
178
+ export type NEARExportFormat = 'csv' | 'json'
179
+
180
+ /**
181
+ * Export options
182
+ */
183
+ export interface NEARExportOptions {
184
+ /** Export format */
185
+ format: NEARExportFormat
186
+
187
+ /** Include headers in CSV */
188
+ includeHeaders?: boolean
189
+
190
+ /** Fields to include (default: all) */
191
+ fields?: (keyof NEARHistoricalTransaction)[]
192
+
193
+ /** Pretty print JSON */
194
+ prettyPrint?: boolean
195
+ }
196
+
197
+ /**
198
+ * Network type for history queries
199
+ */
200
+ type HistoryNetwork = 'mainnet' | 'testnet'
201
+
202
+ // ─── Constants ────────────────────────────────────────────────────────────────
203
+
204
+ const DEFAULT_LIMIT = 50
205
+ const DEFAULT_TIMEOUT = 30000
206
+
207
+ // ─── Utility Functions ────────────────────────────────────────────────────────
208
+
209
+ /**
210
+ * Format amount with decimals
211
+ */
212
+ function formatAmount(amount: bigint, decimals: number): string {
213
+ const str = amount.toString()
214
+ if (decimals === 0) return str
215
+
216
+ const padded = str.padStart(decimals + 1, '0')
217
+ const intPart = padded.slice(0, -decimals) || '0'
218
+ const fracPart = padded.slice(-decimals).replace(/0+$/, '')
219
+
220
+ return fracPart ? `${intPart}.${fracPart}` : intPart
221
+ }
222
+
223
+ /**
224
+ * Determine transaction type based on context
225
+ */
226
+ function classifyTransaction(
227
+ _payment: NEARDetectedPaymentResult,
228
+ _userStealthAddresses: Set<string>
229
+ ): NEARTransactionType {
230
+ // For now, all detected payments are "receive" type
231
+ // TODO: Track outgoing transactions when we have sender info
232
+ return 'receive'
233
+ }
234
+
235
+ /**
236
+ * Determine privacy level from transaction metadata
237
+ */
238
+ function determinePrivacyLevel(): NEARHistoryPrivacyLevel {
239
+ // All stealth address transactions are at least "shielded"
240
+ // "compliant" would require viewing key metadata in the announcement
241
+ return 'shielded'
242
+ }
243
+
244
+ /**
245
+ * Convert detected payment to historical transaction format
246
+ */
247
+ function paymentToTransaction(
248
+ payment: NEARDetectedPaymentResult,
249
+ network: 'mainnet' | 'testnet',
250
+ userStealthAddresses: Set<string>
251
+ ): NEARHistoricalTransaction {
252
+ const type = classifyTransaction(payment, userStealthAddresses)
253
+ const privacyLevel = determinePrivacyLevel()
254
+ const token = payment.tokenContract ? getTokenSymbol(payment.tokenContract) : 'NEAR'
255
+
256
+ return {
257
+ hash: payment.txHash,
258
+ timestamp: Math.floor(payment.timestamp / 1_000_000), // nanoseconds to milliseconds
259
+ blockHeight: payment.blockHeight,
260
+ type,
261
+ stealthAddress: payment.stealthAddress,
262
+ stealthPublicKey: payment.stealthPublicKey,
263
+ ephemeralPublicKey: payment.ephemeralPublicKey,
264
+ viewTag: payment.viewTag,
265
+ amount: payment.amount.toString(),
266
+ amountFormatted: formatAmount(payment.amount, payment.decimals),
267
+ token,
268
+ tokenContract: payment.tokenContract,
269
+ decimals: payment.decimals,
270
+ privacyLevel,
271
+ amountRevealed: true, // Amount is revealed via viewing key
272
+ explorerUrl: getExplorerUrl(payment.txHash, network),
273
+ recipientLabel: payment.recipientLabel,
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Get token symbol from contract address
279
+ */
280
+ function getTokenSymbol(tokenContract: string): string {
281
+ // Well-known tokens
282
+ const knownTokens: Record<string, string> = {
283
+ 'wrap.near': 'wNEAR',
284
+ 'usdt.tether-token.near': 'USDT',
285
+ 'usdc.near': 'USDC',
286
+ 'aurora': 'AURORA',
287
+ 'meta-pool.near': 'stNEAR',
288
+ 'linear-protocol.near': 'LiNEAR',
289
+ }
290
+
291
+ return knownTokens[tokenContract] || tokenContract.split('.')[0].toUpperCase()
292
+ }
293
+
294
+ /**
295
+ * Apply filters to transactions
296
+ */
297
+ function applyFilters(
298
+ transactions: NEARHistoricalTransaction[],
299
+ params: NEARTransactionHistoryParams
300
+ ): NEARHistoricalTransaction[] {
301
+ let filtered = transactions
302
+
303
+ // Filter by timestamp range
304
+ if (params.fromTimestamp) {
305
+ filtered = filtered.filter(tx => tx.timestamp >= params.fromTimestamp!)
306
+ }
307
+ if (params.toTimestamp) {
308
+ filtered = filtered.filter(tx => tx.timestamp <= params.toTimestamp!)
309
+ }
310
+
311
+ // Filter by transaction type
312
+ if (params.typeFilter && params.typeFilter.length > 0) {
313
+ filtered = filtered.filter(tx => params.typeFilter!.includes(tx.type))
314
+ }
315
+
316
+ // Filter by token
317
+ if (params.tokenFilter && params.tokenFilter.length > 0) {
318
+ filtered = filtered.filter(tx => params.tokenFilter!.includes(tx.tokenContract))
319
+ }
320
+
321
+ // Search by hash or address
322
+ if (params.searchQuery) {
323
+ const query = params.searchQuery.toLowerCase()
324
+ filtered = filtered.filter(tx =>
325
+ tx.hash.toLowerCase().includes(query) ||
326
+ tx.stealthAddress.toLowerCase().includes(query) ||
327
+ (tx.sender && tx.sender.toLowerCase().includes(query)) ||
328
+ (tx.receiver && tx.receiver.toLowerCase().includes(query))
329
+ )
330
+ }
331
+
332
+ return filtered
333
+ }
334
+
335
+ // ─── Main Functions ───────────────────────────────────────────────────────────
336
+
337
+ /**
338
+ * Get transaction history for a NEAR privacy wallet
339
+ *
340
+ * Scans the blockchain for stealth address announcements and returns
341
+ * transactions belonging to the provided viewing key.
342
+ *
343
+ * Note: In production, this would integrate with a blockchain indexer
344
+ * for efficient announcement fetching. Currently uses the scanner API
345
+ * which requires announcements to be pre-fetched.
346
+ *
347
+ * @param params - History retrieval parameters
348
+ * @returns Transaction history result with pagination
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * const history = await getTransactionHistory({
353
+ * rpcUrl: 'https://rpc.mainnet.near.org',
354
+ * viewingPrivateKey: '0x...',
355
+ * spendingPrivateKey: '0x...',
356
+ * limit: 20,
357
+ * })
358
+ *
359
+ * for (const tx of history.transactions) {
360
+ * console.log(`${tx.type}: ${tx.amountFormatted} ${tx.token}`)
361
+ * }
362
+ * ```
363
+ */
364
+ export async function getTransactionHistory(
365
+ params: NEARTransactionHistoryParams
366
+ ): Promise<NEARTransactionHistoryResult> {
367
+ const startTime = Date.now()
368
+
369
+ // Validate inputs
370
+ if (!params.rpcUrl) {
371
+ throw new ValidationError('rpcUrl is required')
372
+ }
373
+ if (!isValidHex(params.viewingPrivateKey)) {
374
+ throw new ValidationError('Invalid viewing private key')
375
+ }
376
+ if (!isValidHex(params.spendingPrivateKey)) {
377
+ throw new ValidationError('Invalid spending private key')
378
+ }
379
+
380
+ const network: HistoryNetwork = params.network === 'testnet' ? 'testnet' : 'mainnet'
381
+ const limit = params.limit ?? DEFAULT_LIMIT
382
+ const timeout = params.timeout ?? DEFAULT_TIMEOUT
383
+
384
+ // Create scanner and add recipient
385
+ const scanner = createNEARStealthScanner({
386
+ rpcUrl: params.rpcUrl,
387
+ network,
388
+ timeout,
389
+ })
390
+
391
+ scanner.addRecipient({
392
+ viewingPrivateKey: params.viewingPrivateKey,
393
+ spendingPrivateKey: params.spendingPrivateKey,
394
+ })
395
+
396
+ // Fetch announcements from the chain
397
+ // This is a placeholder - in production, use an indexer service
398
+ const announcements = await fetchAnnouncementsFromChain(params.rpcUrl, {
399
+ fromBlock: params.fromBlock,
400
+ toBlock: params.toBlock,
401
+ limit: limit * 2, // Over-fetch to account for filtering
402
+ })
403
+
404
+ // Scan announcements for payments to this recipient
405
+ const payments = await scanner.scanAnnouncements(
406
+ announcements.items,
407
+ announcements.metadata
408
+ )
409
+
410
+ // Track user's stealth addresses for type classification
411
+ const userStealthAddresses = new Set<string>(
412
+ payments.map((p: NEARDetectedPaymentResult) => p.stealthAddress)
413
+ )
414
+
415
+ // Convert to historical transaction format
416
+ let transactions = payments.map((payment: NEARDetectedPaymentResult) =>
417
+ paymentToTransaction(payment, network, userStealthAddresses)
418
+ )
419
+
420
+ // Apply filters
421
+ transactions = applyFilters(transactions, params)
422
+
423
+ // Sort by timestamp descending (newest first)
424
+ transactions.sort((a: NEARHistoricalTransaction, b: NEARHistoricalTransaction) =>
425
+ b.timestamp - a.timestamp
426
+ )
427
+
428
+ // Apply limit after filtering
429
+ const hasMore = transactions.length > limit || announcements.hasMore
430
+ transactions = transactions.slice(0, limit)
431
+
432
+ return {
433
+ transactions,
434
+ totalCount: announcements.scannedCount,
435
+ hasMore,
436
+ nextCursor: announcements.nextCursor,
437
+ lastBlockHeight: announcements.lastBlockHeight,
438
+ scanTimeMs: Date.now() - startTime,
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Fetch SIP announcements from the NEAR blockchain
444
+ *
445
+ * This is a placeholder implementation. In production, this would:
446
+ * 1. Query an indexer service for SIP: memo prefixed transactions
447
+ * 2. Parse announcements from transaction logs
448
+ * 3. Support pagination via cursor
449
+ *
450
+ * @internal
451
+ */
452
+ async function fetchAnnouncementsFromChain(
453
+ _rpcUrl: string,
454
+ _options: {
455
+ fromBlock?: number
456
+ toBlock?: number
457
+ limit?: number
458
+ cursor?: string
459
+ }
460
+ ): Promise<{
461
+ items: Array<{
462
+ ephemeralPublicKey: HexString
463
+ viewTag: number
464
+ stealthAddress: HexString
465
+ stealthAccountId: string
466
+ }>
467
+ metadata: Array<{
468
+ txHash: string
469
+ blockHeight: number
470
+ timestamp: number
471
+ amount?: bigint
472
+ tokenContract?: string
473
+ decimals?: number
474
+ }>
475
+ scannedCount: number
476
+ hasMore: boolean
477
+ nextCursor?: string
478
+ lastBlockHeight?: number
479
+ }> {
480
+ // TODO: Implement actual indexer integration
481
+ // This placeholder returns empty results until indexer is available
482
+ //
483
+ // Production implementation would:
484
+ // 1. Query NEAR Indexer for transactions with SIP: memo prefix
485
+ // 2. Parse announcements from transaction receipts/logs
486
+ // 3. Extract stealth address from transaction receiver
487
+ // 4. Support cursor-based pagination
488
+
489
+ return {
490
+ items: [],
491
+ metadata: [],
492
+ scannedCount: 0,
493
+ hasMore: false,
494
+ nextCursor: undefined,
495
+ lastBlockHeight: _options.toBlock,
496
+ }
497
+ }
498
+
499
+ /**
500
+ * Export transactions to CSV or JSON format
501
+ *
502
+ * @param transactions - Transactions to export
503
+ * @param options - Export options
504
+ * @returns Formatted string in the specified format
505
+ *
506
+ * @example
507
+ * ```typescript
508
+ * const csv = exportTransactions(history.transactions, { format: 'csv' })
509
+ * downloadFile('transactions.csv', csv, 'text/csv')
510
+ *
511
+ * const json = exportTransactions(history.transactions, {
512
+ * format: 'json',
513
+ * prettyPrint: true,
514
+ * })
515
+ * ```
516
+ */
517
+ export function exportTransactions(
518
+ transactions: NEARHistoricalTransaction[],
519
+ options: NEARExportOptions
520
+ ): string {
521
+ const { format, includeHeaders = true, fields, prettyPrint = false } = options
522
+
523
+ // Default fields for export
524
+ const defaultFields: (keyof NEARHistoricalTransaction)[] = [
525
+ 'hash',
526
+ 'timestamp',
527
+ 'type',
528
+ 'amountFormatted',
529
+ 'token',
530
+ 'stealthAddress',
531
+ 'privacyLevel',
532
+ 'explorerUrl',
533
+ ]
534
+
535
+ const exportFields = fields ?? defaultFields
536
+
537
+ if (format === 'json') {
538
+ const data = transactions.map(tx => {
539
+ const obj: Partial<NEARHistoricalTransaction> = {}
540
+ for (const field of exportFields) {
541
+ obj[field] = tx[field] as never
542
+ }
543
+ return obj
544
+ })
545
+ return prettyPrint ? JSON.stringify(data, null, 2) : JSON.stringify(data)
546
+ }
547
+
548
+ // CSV format
549
+ const rows: string[] = []
550
+
551
+ if (includeHeaders) {
552
+ rows.push(exportFields.join(','))
553
+ }
554
+
555
+ for (const tx of transactions) {
556
+ const values = exportFields.map(field => {
557
+ const value = tx[field]
558
+ if (value === null || value === undefined) return ''
559
+ if (typeof value === 'string' && value.includes(',')) {
560
+ return `"${value.replace(/"/g, '""')}"`
561
+ }
562
+ return String(value)
563
+ })
564
+ rows.push(values.join(','))
565
+ }
566
+
567
+ return rows.join('\n')
568
+ }
569
+
570
+ /**
571
+ * Get transaction by hash
572
+ *
573
+ * @param hash - Transaction hash to look up
574
+ * @param params - History parameters (for authentication)
575
+ * @returns Transaction if found and owned, null otherwise
576
+ */
577
+ export async function getTransactionByHash(
578
+ hash: string,
579
+ params: Omit<NEARTransactionHistoryParams, 'searchQuery' | 'limit'>
580
+ ): Promise<NEARHistoricalTransaction | null> {
581
+ const result = await getTransactionHistory({
582
+ ...params,
583
+ searchQuery: hash,
584
+ limit: 1,
585
+ })
586
+
587
+ return result.transactions[0] ?? null
588
+ }
589
+
590
+ /**
591
+ * Get transaction count for a date range
592
+ *
593
+ * @param params - History parameters
594
+ * @returns Count of transactions in the range
595
+ */
596
+ export async function getTransactionCount(
597
+ params: Omit<NEARTransactionHistoryParams, 'limit' | 'cursor'>
598
+ ): Promise<number> {
599
+ const result = await getTransactionHistory({
600
+ ...params,
601
+ limit: 10000, // High limit to get total count
602
+ })
603
+
604
+ return result.transactions.length
605
+ }
606
+
607
+ /**
608
+ * Get transaction summary statistics
609
+ *
610
+ * @param transactions - Transactions to summarize
611
+ * @returns Summary statistics
612
+ */
613
+ export function getTransactionSummary(transactions: NEARHistoricalTransaction[]): {
614
+ totalReceived: Record<string, bigint>
615
+ totalSent: Record<string, bigint>
616
+ transactionCount: number
617
+ uniqueAddresses: number
618
+ dateRange: { from: number; to: number } | null
619
+ } {
620
+ const totalReceived: Record<string, bigint> = {}
621
+ const totalSent: Record<string, bigint> = {}
622
+ const addresses = new Set<string>()
623
+
624
+ let minTimestamp = Infinity
625
+ let maxTimestamp = -Infinity
626
+
627
+ for (const tx of transactions) {
628
+ const token = tx.token
629
+ const amount = BigInt(tx.amount)
630
+
631
+ if (tx.type === 'receive') {
632
+ totalReceived[token] = (totalReceived[token] ?? 0n) + amount
633
+ } else if (tx.type === 'send') {
634
+ totalSent[token] = (totalSent[token] ?? 0n) + amount
635
+ }
636
+
637
+ addresses.add(tx.stealthAddress)
638
+ if (tx.sender) addresses.add(tx.sender)
639
+ if (tx.receiver) addresses.add(tx.receiver)
640
+
641
+ minTimestamp = Math.min(minTimestamp, tx.timestamp)
642
+ maxTimestamp = Math.max(maxTimestamp, tx.timestamp)
643
+ }
644
+
645
+ return {
646
+ totalReceived,
647
+ totalSent,
648
+ transactionCount: transactions.length,
649
+ uniqueAddresses: addresses.size,
650
+ dateRange: transactions.length > 0
651
+ ? { from: minTimestamp, to: maxTimestamp }
652
+ : null,
653
+ }
654
+ }