@sip-protocol/sdk 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +267 -0
- package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
- package/dist/browser.d.mts +10 -4
- package/dist/browser.d.ts +10 -4
- package/dist/browser.js +47556 -19603
- package/dist/browser.mjs +628 -48
- package/dist/chunk-4GRJ5MAW.mjs +152 -0
- package/dist/chunk-5D7A3L3W.mjs +717 -0
- package/dist/chunk-64AYA5F5.mjs +7834 -0
- package/dist/chunk-GMDGB22A.mjs +379 -0
- package/dist/chunk-I534WKN7.mjs +328 -0
- package/dist/chunk-IBZVA5Y7.mjs +1003 -0
- package/dist/chunk-PRRZAWJE.mjs +223 -0
- package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
- package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
- package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
- package/dist/constants-LHAAUC2T.mjs +51 -0
- package/dist/dist-2OGQ7FED.mjs +3957 -0
- package/dist/dist-IFHPYLDX.mjs +254 -0
- package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
- package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
- package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
- package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48396 -19623
- package/dist/index.mjs +537 -19
- package/dist/interface-Bf7w1PLW.d.mts +679 -0
- package/dist/interface-Bf7w1PLW.d.ts +679 -0
- package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
- package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
- package/dist/proofs/halo2.d.mts +151 -0
- package/dist/proofs/halo2.d.ts +151 -0
- package/dist/proofs/halo2.js +350 -0
- package/dist/proofs/halo2.mjs +11 -0
- package/dist/proofs/kimchi.d.mts +160 -0
- package/dist/proofs/kimchi.d.ts +160 -0
- package/dist/proofs/kimchi.js +431 -0
- package/dist/proofs/kimchi.mjs +13 -0
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +74 -18
- package/dist/proofs/noir.mjs +84 -24
- package/dist/solana-U3MEGU7W.mjs +280 -0
- package/dist/validity_proof-3POXLPNY.mjs +21 -0
- package/package.json +44 -11
- package/src/adapters/index.ts +41 -0
- package/src/adapters/jupiter.ts +571 -0
- package/src/adapters/near-intents.ts +135 -0
- package/src/advisor/advisor.ts +653 -0
- package/src/advisor/index.ts +54 -0
- package/src/advisor/tools.ts +303 -0
- package/src/advisor/types.ts +164 -0
- package/src/chains/ethereum/announcement.ts +536 -0
- package/src/chains/ethereum/bnb-optimizations.ts +474 -0
- package/src/chains/ethereum/commitment.ts +522 -0
- package/src/chains/ethereum/constants.ts +462 -0
- package/src/chains/ethereum/deployment.ts +596 -0
- package/src/chains/ethereum/gas-estimation.ts +538 -0
- package/src/chains/ethereum/index.ts +268 -0
- package/src/chains/ethereum/optimizations.ts +614 -0
- package/src/chains/ethereum/privacy-adapter.ts +855 -0
- package/src/chains/ethereum/registry.ts +584 -0
- package/src/chains/ethereum/rpc.ts +905 -0
- package/src/chains/ethereum/stealth.ts +491 -0
- package/src/chains/ethereum/token.ts +790 -0
- package/src/chains/ethereum/transfer.ts +637 -0
- package/src/chains/ethereum/types.ts +456 -0
- package/src/chains/ethereum/viewing-key.ts +455 -0
- package/src/chains/near/commitment.ts +608 -0
- package/src/chains/near/constants.ts +284 -0
- package/src/chains/near/function-call.ts +871 -0
- package/src/chains/near/history.ts +654 -0
- package/src/chains/near/implicit-account.ts +840 -0
- package/src/chains/near/index.ts +393 -0
- package/src/chains/near/native-transfer.ts +658 -0
- package/src/chains/near/nep141.ts +775 -0
- package/src/chains/near/privacy-adapter.ts +889 -0
- package/src/chains/near/resolver.ts +971 -0
- package/src/chains/near/rpc.ts +1016 -0
- package/src/chains/near/stealth.ts +419 -0
- package/src/chains/near/types.ts +317 -0
- package/src/chains/near/viewing-key.ts +876 -0
- package/src/chains/solana/anchor-transfer.ts +386 -0
- package/src/chains/solana/commitment.ts +577 -0
- package/src/chains/solana/constants.ts +126 -12
- package/src/chains/solana/ephemeral-keys.ts +543 -0
- package/src/chains/solana/index.ts +252 -1
- package/src/chains/solana/key-derivation.ts +418 -0
- package/src/chains/solana/kit-compat.ts +334 -0
- package/src/chains/solana/optimizations.ts +560 -0
- package/src/chains/solana/privacy-adapter.ts +605 -0
- package/src/chains/solana/providers/generic.ts +47 -6
- package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
- package/src/chains/solana/providers/helius-enhanced.ts +623 -0
- package/src/chains/solana/providers/helius.ts +186 -33
- package/src/chains/solana/providers/index.ts +31 -0
- package/src/chains/solana/providers/interface.ts +61 -18
- package/src/chains/solana/providers/quicknode.ts +409 -0
- package/src/chains/solana/providers/triton.ts +426 -0
- package/src/chains/solana/providers/webhook.ts +338 -67
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +83 -66
- package/src/chains/solana/sol-transfer.ts +732 -0
- package/src/chains/solana/spl-transfer.ts +886 -0
- package/src/chains/solana/stealth-scanner.ts +703 -0
- package/src/chains/solana/sunspot-verifier.ts +453 -0
- package/src/chains/solana/transaction-builder.ts +755 -0
- package/src/chains/solana/transfer.ts +74 -5
- package/src/chains/solana/types.ts +57 -6
- package/src/chains/solana/utils.ts +110 -0
- package/src/chains/solana/viewing-key.ts +807 -0
- package/src/compliance/fireblocks.ts +921 -0
- package/src/compliance/index.ts +23 -0
- package/src/compliance/range-sas.ts +398 -33
- package/src/config/endpoints.ts +100 -0
- package/src/crypto.ts +11 -8
- package/src/errors.ts +82 -0
- package/src/evm/erc4337-relayer.ts +830 -0
- package/src/evm/index.ts +47 -0
- package/src/fees/calculator.ts +396 -0
- package/src/fees/index.ts +87 -0
- package/src/fees/near-contract.ts +429 -0
- package/src/fees/types.ts +268 -0
- package/src/index.ts +686 -1
- package/src/intent.ts +6 -3
- package/src/logger.ts +324 -0
- package/src/network/index.ts +80 -0
- package/src/network/proxy.ts +691 -0
- package/src/optimizations/index.ts +541 -0
- package/src/oracle/types.ts +1 -0
- package/src/privacy-backends/arcium-types.ts +727 -0
- package/src/privacy-backends/arcium.ts +719 -0
- package/src/privacy-backends/combined-privacy.ts +866 -0
- package/src/privacy-backends/cspl-token.ts +595 -0
- package/src/privacy-backends/cspl-types.ts +512 -0
- package/src/privacy-backends/cspl.ts +907 -0
- package/src/privacy-backends/health.ts +488 -0
- package/src/privacy-backends/inco-types.ts +323 -0
- package/src/privacy-backends/inco.ts +616 -0
- package/src/privacy-backends/index.ts +254 -4
- package/src/privacy-backends/interface.ts +649 -6
- package/src/privacy-backends/lru-cache.ts +343 -0
- package/src/privacy-backends/magicblock.ts +458 -0
- package/src/privacy-backends/mock.ts +258 -0
- package/src/privacy-backends/privacycash.ts +13 -17
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +414 -2
- package/src/privacy-backends/router.ts +283 -3
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +3 -0
- package/src/privacy-logger.ts +191 -0
- package/src/production-safety.ts +373 -0
- package/src/proofs/aggregator.ts +1029 -0
- package/src/proofs/browser-composer.ts +1150 -0
- package/src/proofs/browser.ts +113 -25
- package/src/proofs/cache/index.ts +127 -0
- package/src/proofs/cache/interface.ts +545 -0
- package/src/proofs/cache/key-generator.ts +188 -0
- package/src/proofs/cache/lru-cache.ts +481 -0
- package/src/proofs/cache/multi-tier-cache.ts +575 -0
- package/src/proofs/cache/persistent-cache.ts +788 -0
- package/src/proofs/compliance-proof.ts +872 -0
- package/src/proofs/composer/base.ts +923 -0
- package/src/proofs/composer/index.ts +25 -0
- package/src/proofs/composer/interface.ts +518 -0
- package/src/proofs/composer/types.ts +383 -0
- package/src/proofs/converters/halo2.ts +452 -0
- package/src/proofs/converters/index.ts +208 -0
- package/src/proofs/converters/interface.ts +363 -0
- package/src/proofs/converters/kimchi.ts +462 -0
- package/src/proofs/converters/noir.ts +451 -0
- package/src/proofs/fallback.ts +888 -0
- package/src/proofs/halo2.ts +42 -0
- package/src/proofs/index.ts +471 -0
- package/src/proofs/interface.ts +13 -0
- package/src/proofs/kimchi.ts +42 -0
- package/src/proofs/lazy.ts +1004 -0
- package/src/proofs/mock.ts +25 -1
- package/src/proofs/noir.ts +110 -29
- package/src/proofs/orchestrator.ts +960 -0
- package/src/proofs/parallel/concurrency.ts +297 -0
- package/src/proofs/parallel/dependency-graph.ts +602 -0
- package/src/proofs/parallel/executor.ts +420 -0
- package/src/proofs/parallel/index.ts +131 -0
- package/src/proofs/parallel/interface.ts +685 -0
- package/src/proofs/parallel/worker-pool.ts +644 -0
- package/src/proofs/providers/halo2.ts +560 -0
- package/src/proofs/providers/index.ts +34 -0
- package/src/proofs/providers/kimchi.ts +641 -0
- package/src/proofs/validator.ts +881 -0
- package/src/proofs/verifier.ts +867 -0
- package/src/quantum/index.ts +112 -0
- package/src/quantum/winternitz-vault.ts +639 -0
- package/src/quantum/wots.ts +611 -0
- package/src/settlement/backends/direct-chain.ts +1 -0
- package/src/settlement/index.ts +9 -0
- package/src/settlement/router.ts +732 -46
- package/src/solana/index.ts +72 -0
- package/src/solana/jito-relayer.ts +687 -0
- package/src/solana/noir-verifier-types.ts +430 -0
- package/src/solana/noir-verifier.ts +816 -0
- package/src/stealth/address-derivation.ts +193 -0
- package/src/stealth/ed25519.ts +431 -0
- package/src/stealth/index.ts +233 -0
- package/src/stealth/meta-address.ts +221 -0
- package/src/stealth/secp256k1.ts +368 -0
- package/src/stealth/utils.ts +194 -0
- package/src/stealth.ts +50 -1504
- package/src/sync/index.ts +106 -0
- package/src/sync/manager.ts +504 -0
- package/src/sync/mock-provider.ts +318 -0
- package/src/sync/oblivious.ts +625 -0
- package/src/tokens/index.ts +15 -0
- package/src/tokens/registry.ts +301 -0
- package/src/utils/deprecation.ts +94 -0
- package/src/utils/index.ts +9 -0
- package/src/wallet/ethereum/index.ts +68 -0
- package/src/wallet/ethereum/metamask-privacy.ts +420 -0
- package/src/wallet/ethereum/multi-wallet.ts +646 -0
- package/src/wallet/ethereum/privacy-adapter.ts +700 -0
- package/src/wallet/ethereum/types.ts +3 -1
- package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
- package/src/wallet/hardware/index.ts +10 -0
- package/src/wallet/hardware/ledger-privacy.ts +414 -0
- package/src/wallet/index.ts +71 -0
- package/src/wallet/near/adapter.ts +626 -0
- package/src/wallet/near/index.ts +86 -0
- package/src/wallet/near/meteor-wallet.ts +1153 -0
- package/src/wallet/near/my-near-wallet.ts +790 -0
- package/src/wallet/near/wallet-selector.ts +702 -0
- package/src/wallet/solana/adapter.ts +6 -4
- package/src/wallet/solana/index.ts +13 -0
- package/src/wallet/solana/privacy-adapter.ts +567 -0
- package/src/wallet/sui/types.ts +6 -4
- package/src/zcash/rpc-client.ts +13 -6
- package/dist/chunk-2XIVXWHA.mjs +0 -1930
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-7RFRWDCW.mjs +0 -1504
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-F6F73W35.mjs +0 -16166
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-OFDBEIEK.mjs +0 -16166
- package/dist/chunk-SF7YSLF5.mjs +0 -1515
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/chunk-WWUSGOXE.mjs +0 -17129
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-B71aXVzk.d.ts +0 -13264
- package/dist/index-BYZbDjal.d.ts +0 -11390
- package/dist/index-CHB3KuOB.d.mts +0 -11859
- package/dist/index-CzWPI6Le.d.ts +0 -11859
- package/dist/index-pOIIuwfV.d.mts +0 -13264
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-4O4K45VU.mjs +0 -46
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-NDABAZ6P.mjs +0 -56
- package/dist/solana-Q4NAVBTS.mjs +0 -46
- package/dist/solana-ZYO63LY5.mjs +0 -46
|
@@ -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
|
+
}
|