@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.
- package/LICENSE +21 -0
- 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 +48874 -18336
- package/dist/browser.mjs +674 -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-YWGJ77A2.mjs +33806 -0
- 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-DXh2IGkz.d.ts +24681 -0
- package/dist/index-DeE1ZzA4.d.mts +24681 -0
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48676 -17318
- package/dist/index.mjs +583 -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 +54 -21
- 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 +276 -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 +201 -0
- 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 +402 -0
- package/src/chains/solana/providers/index.ts +85 -0
- package/src/chains/solana/providers/interface.ts +221 -0
- 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 +790 -0
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +170 -73
- 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 +77 -7
- 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 +37 -0
- package/src/compliance/range-sas.ts +956 -0
- 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 +785 -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 +336 -0
- package/src/privacy-backends/interface.ts +906 -0
- 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-types.ts +278 -0
- package/src/privacy-backends/privacycash.ts +456 -0
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +690 -0
- package/src/privacy-backends/router.ts +626 -0
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +256 -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 +111 -30
- 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/surveillance/algorithms/address-reuse.ts +143 -0
- package/src/surveillance/algorithms/cluster.ts +247 -0
- package/src/surveillance/algorithms/exchange.ts +295 -0
- package/src/surveillance/algorithms/temporal.ts +337 -0
- package/src/surveillance/analyzer.ts +442 -0
- package/src/surveillance/index.ts +64 -0
- package/src/surveillance/scoring.ts +372 -0
- package/src/surveillance/types.ts +264 -0
- 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-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/constants-VOI7BSLK.mjs +0 -27
- 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-xbWjohNq.d.mts +0 -11390
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-Q4NAVBTS.mjs +0 -46
|
@@ -0,0 +1,790 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MyNearWallet Privacy Integration
|
|
3
|
+
*
|
|
4
|
+
* Specific integration for MyNearWallet with privacy transaction support.
|
|
5
|
+
* Handles URL-based transaction signing and callback processing.
|
|
6
|
+
*
|
|
7
|
+
* @example Basic usage
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { MyNearWalletPrivacy } from '@sip-protocol/sdk'
|
|
10
|
+
*
|
|
11
|
+
* const wallet = new MyNearWalletPrivacy({
|
|
12
|
+
* network: 'mainnet',
|
|
13
|
+
* callbackUrl: 'https://myapp.com/callback',
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // Connect to wallet
|
|
17
|
+
* await wallet.connect()
|
|
18
|
+
*
|
|
19
|
+
* // Send private transfer (redirects to MyNearWallet)
|
|
20
|
+
* await wallet.sendPrivateTransfer({
|
|
21
|
+
* recipientMetaAddress: 'sip:near:0x...',
|
|
22
|
+
* amount: '1000000000000000000000000',
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { sha256 } from '@noble/hashes/sha2'
|
|
30
|
+
import { bytesToHex } from '@noble/hashes/utils'
|
|
31
|
+
import { ed25519 } from '@noble/curves/ed25519'
|
|
32
|
+
import type { HexString, StealthMetaAddress, StealthAddress } from '@sip-protocol/types'
|
|
33
|
+
import type { NEARNetwork } from '../../chains/near/constants'
|
|
34
|
+
import {
|
|
35
|
+
generateNEARStealthAddress,
|
|
36
|
+
deriveNEARStealthPrivateKey,
|
|
37
|
+
checkNEARStealthAddress,
|
|
38
|
+
encodeNEARStealthMetaAddress,
|
|
39
|
+
parseNEARStealthMetaAddress,
|
|
40
|
+
} from '../../chains/near/stealth'
|
|
41
|
+
import { buildPrivateTransfer } from '../../chains/near/implicit-account'
|
|
42
|
+
|
|
43
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
/** MyNearWallet mainnet URL */
|
|
46
|
+
export const MY_NEAR_WALLET_MAINNET = 'https://app.mynearwallet.com'
|
|
47
|
+
|
|
48
|
+
/** MyNearWallet testnet URL */
|
|
49
|
+
export const MY_NEAR_WALLET_TESTNET = 'https://testnet.mynearwallet.com'
|
|
50
|
+
|
|
51
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* MyNearWallet configuration
|
|
55
|
+
*/
|
|
56
|
+
export interface MyNearWalletConfig {
|
|
57
|
+
/** NEAR network */
|
|
58
|
+
network: NEARNetwork
|
|
59
|
+
/** Callback URL after signing */
|
|
60
|
+
callbackUrl: string
|
|
61
|
+
/** Custom wallet URL (optional) */
|
|
62
|
+
walletUrl?: string
|
|
63
|
+
/** Contract ID for function calls (optional) */
|
|
64
|
+
contractId?: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Connection state
|
|
69
|
+
*/
|
|
70
|
+
export type MyNearWalletConnectionState =
|
|
71
|
+
| 'disconnected'
|
|
72
|
+
| 'connecting'
|
|
73
|
+
| 'connected'
|
|
74
|
+
| 'signing'
|
|
75
|
+
| 'error'
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Privacy key pair
|
|
79
|
+
*/
|
|
80
|
+
export interface MyNearWalletPrivacyKeys {
|
|
81
|
+
spendingPrivateKey: HexString
|
|
82
|
+
spendingPublicKey: HexString
|
|
83
|
+
viewingPrivateKey: HexString
|
|
84
|
+
viewingPublicKey: HexString
|
|
85
|
+
derivationLabel: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Stealth address with metadata
|
|
90
|
+
*/
|
|
91
|
+
export interface MyNearWalletStealthAddress {
|
|
92
|
+
stealthAddress: StealthAddress
|
|
93
|
+
stealthAccountId: string
|
|
94
|
+
ephemeralPublicKey: HexString
|
|
95
|
+
createdAt: number
|
|
96
|
+
label?: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Private transfer parameters
|
|
101
|
+
*/
|
|
102
|
+
export interface MyNearWalletPrivateTransferParams {
|
|
103
|
+
/** Recipient's stealth meta-address */
|
|
104
|
+
recipientMetaAddress: string | StealthMetaAddress
|
|
105
|
+
/** Amount in yoctoNEAR */
|
|
106
|
+
amount: string | bigint
|
|
107
|
+
/** Optional memo */
|
|
108
|
+
memo?: string
|
|
109
|
+
/** Optional label for tracking */
|
|
110
|
+
label?: string
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Transaction preview data
|
|
115
|
+
*/
|
|
116
|
+
export interface TransactionPreview {
|
|
117
|
+
/** Sender account ID */
|
|
118
|
+
senderId: string
|
|
119
|
+
/** Receiver (stealth account ID) */
|
|
120
|
+
receiverId: string
|
|
121
|
+
/** Amount in NEAR (formatted) */
|
|
122
|
+
amountNEAR: string
|
|
123
|
+
/** Amount in yoctoNEAR */
|
|
124
|
+
amountYocto: string
|
|
125
|
+
/** Is this a privacy transaction */
|
|
126
|
+
isPrivate: true
|
|
127
|
+
/** Stealth address info */
|
|
128
|
+
stealthInfo: {
|
|
129
|
+
stealthAccountId: string
|
|
130
|
+
announcementMemo: string
|
|
131
|
+
viewTag: number
|
|
132
|
+
}
|
|
133
|
+
/** Actions to execute */
|
|
134
|
+
actions: Array<{
|
|
135
|
+
type: string
|
|
136
|
+
params: Record<string, unknown>
|
|
137
|
+
}>
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Callback result from MyNearWallet
|
|
142
|
+
*/
|
|
143
|
+
export interface MyNearWalletCallbackResult {
|
|
144
|
+
/** Transaction hash (if successful) */
|
|
145
|
+
transactionHashes?: string
|
|
146
|
+
/** Error code (if failed) */
|
|
147
|
+
errorCode?: string
|
|
148
|
+
/** Error message (if failed) */
|
|
149
|
+
errorMessage?: string
|
|
150
|
+
/** Account ID that signed */
|
|
151
|
+
accountId?: string
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Viewing key export
|
|
156
|
+
*/
|
|
157
|
+
export interface MyNearWalletViewingKeyExport {
|
|
158
|
+
network: NEARNetwork
|
|
159
|
+
viewingPublicKey: HexString
|
|
160
|
+
viewingPrivateKey: HexString
|
|
161
|
+
spendingPublicKey: HexString
|
|
162
|
+
accountId: string
|
|
163
|
+
createdAt: number
|
|
164
|
+
label?: string
|
|
165
|
+
walletType: 'mynearwallet'
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Ledger integration status
|
|
170
|
+
*/
|
|
171
|
+
export interface LedgerStatus {
|
|
172
|
+
isLedger: boolean
|
|
173
|
+
ledgerPath?: string
|
|
174
|
+
requiresLedgerConfirmation: boolean
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── MyNearWallet Privacy Class ───────────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* MyNearWallet Privacy Integration
|
|
181
|
+
*
|
|
182
|
+
* Provides privacy transaction support for MyNearWallet.
|
|
183
|
+
*/
|
|
184
|
+
export class MyNearWalletPrivacy {
|
|
185
|
+
private config: MyNearWalletConfig
|
|
186
|
+
private walletUrl: string
|
|
187
|
+
private connectionState: MyNearWalletConnectionState = 'disconnected'
|
|
188
|
+
private accountId: string | null = null
|
|
189
|
+
private publicKey: string | null = null
|
|
190
|
+
private privacyKeys: MyNearWalletPrivacyKeys | null = null
|
|
191
|
+
private stealthAddresses: Map<string, MyNearWalletStealthAddress> = new Map()
|
|
192
|
+
private isLedger: boolean = false
|
|
193
|
+
|
|
194
|
+
constructor(config: MyNearWalletConfig) {
|
|
195
|
+
this.config = config
|
|
196
|
+
this.walletUrl = config.walletUrl ?? (
|
|
197
|
+
config.network === 'mainnet'
|
|
198
|
+
? MY_NEAR_WALLET_MAINNET
|
|
199
|
+
: MY_NEAR_WALLET_TESTNET
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ─── Connection ─────────────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Get wallet URL for signing in
|
|
207
|
+
*/
|
|
208
|
+
getSignInUrl(options?: {
|
|
209
|
+
successUrl?: string
|
|
210
|
+
failureUrl?: string
|
|
211
|
+
}): string {
|
|
212
|
+
const params = new URLSearchParams({
|
|
213
|
+
success_url: options?.successUrl ?? this.config.callbackUrl,
|
|
214
|
+
failure_url: options?.failureUrl ?? this.config.callbackUrl,
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
if (this.config.contractId) {
|
|
218
|
+
params.set('contract_id', this.config.contractId)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return `${this.walletUrl}/login?${params.toString()}`
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Connect by redirecting to MyNearWallet
|
|
226
|
+
*/
|
|
227
|
+
connect(options?: {
|
|
228
|
+
successUrl?: string
|
|
229
|
+
failureUrl?: string
|
|
230
|
+
}): void {
|
|
231
|
+
this.connectionState = 'connecting'
|
|
232
|
+
|
|
233
|
+
if (typeof window !== 'undefined') {
|
|
234
|
+
window.location.href = this.getSignInUrl(options)
|
|
235
|
+
} else {
|
|
236
|
+
throw new Error('MyNearWallet connect requires browser environment')
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Handle callback from MyNearWallet login
|
|
242
|
+
*/
|
|
243
|
+
handleLoginCallback(callbackParams: URLSearchParams): boolean {
|
|
244
|
+
const accountId = callbackParams.get('account_id')
|
|
245
|
+
const publicKey = callbackParams.get('public_key')
|
|
246
|
+
const allKeys = callbackParams.get('all_keys')
|
|
247
|
+
|
|
248
|
+
if (accountId) {
|
|
249
|
+
this.accountId = accountId
|
|
250
|
+
this.publicKey = publicKey
|
|
251
|
+
this.connectionState = 'connected'
|
|
252
|
+
|
|
253
|
+
// Check if using Ledger
|
|
254
|
+
if (allKeys) {
|
|
255
|
+
try {
|
|
256
|
+
const keys = JSON.parse(allKeys)
|
|
257
|
+
this.isLedger = keys.some((k: string) => k.includes('ledger'))
|
|
258
|
+
} catch {
|
|
259
|
+
this.isLedger = false
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return true
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.connectionState = 'error'
|
|
267
|
+
return false
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Set connection from stored credentials
|
|
272
|
+
*/
|
|
273
|
+
setConnection(accountId: string, publicKey?: string): void {
|
|
274
|
+
this.accountId = accountId
|
|
275
|
+
this.publicKey = publicKey ?? null
|
|
276
|
+
this.connectionState = 'connected'
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Disconnect
|
|
281
|
+
*/
|
|
282
|
+
disconnect(): void {
|
|
283
|
+
this.accountId = null
|
|
284
|
+
this.publicKey = null
|
|
285
|
+
this.privacyKeys = null
|
|
286
|
+
this.stealthAddresses.clear()
|
|
287
|
+
this.connectionState = 'disconnected'
|
|
288
|
+
this.isLedger = false
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get connection state
|
|
293
|
+
*/
|
|
294
|
+
getConnectionState(): MyNearWalletConnectionState {
|
|
295
|
+
return this.connectionState
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Check if connected
|
|
300
|
+
*/
|
|
301
|
+
isConnected(): boolean {
|
|
302
|
+
return this.connectionState === 'connected' && this.accountId !== null
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get account ID
|
|
307
|
+
*/
|
|
308
|
+
getAccountId(): string | null {
|
|
309
|
+
return this.accountId
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Get public key
|
|
314
|
+
*/
|
|
315
|
+
getPublicKey(): string | null {
|
|
316
|
+
return this.publicKey
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get Ledger status
|
|
321
|
+
*/
|
|
322
|
+
getLedgerStatus(): LedgerStatus {
|
|
323
|
+
return {
|
|
324
|
+
isLedger: this.isLedger,
|
|
325
|
+
requiresLedgerConfirmation: this.isLedger,
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ─── Privacy Key Management ─────────────────────────────────────────────────
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Derive privacy keys
|
|
333
|
+
*
|
|
334
|
+
* Note: MyNearWallet doesn't support message signing directly,
|
|
335
|
+
* so we use a deterministic derivation from account ID + secret.
|
|
336
|
+
*/
|
|
337
|
+
derivePrivacyKeys(secret: string, label: string = 'default'): MyNearWalletPrivacyKeys {
|
|
338
|
+
if (!this.accountId) {
|
|
339
|
+
throw new Error('Not connected to MyNearWallet')
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Create deterministic entropy from account + secret + label
|
|
343
|
+
const derivationPath = `sip/mynearwallet/${this.config.network}/${this.accountId}/${label}`
|
|
344
|
+
const entropy = sha256(
|
|
345
|
+
new TextEncoder().encode(`${derivationPath}:${secret}`)
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
// Derive spending key
|
|
349
|
+
const spendingEntropy = sha256(new Uint8Array([...entropy, 0x01]))
|
|
350
|
+
const spendingPrivateKey = clampScalar(spendingEntropy)
|
|
351
|
+
const spendingPublicKey = ed25519.getPublicKey(spendingPrivateKey)
|
|
352
|
+
|
|
353
|
+
// Derive viewing key
|
|
354
|
+
const viewingEntropy = sha256(new Uint8Array([...entropy, 0x02]))
|
|
355
|
+
const viewingPrivateKey = clampScalar(viewingEntropy)
|
|
356
|
+
const viewingPublicKey = ed25519.getPublicKey(viewingPrivateKey)
|
|
357
|
+
|
|
358
|
+
const keys: MyNearWalletPrivacyKeys = {
|
|
359
|
+
spendingPrivateKey: `0x${bytesToHex(spendingPrivateKey)}` as HexString,
|
|
360
|
+
spendingPublicKey: `0x${bytesToHex(spendingPublicKey)}` as HexString,
|
|
361
|
+
viewingPrivateKey: `0x${bytesToHex(viewingPrivateKey)}` as HexString,
|
|
362
|
+
viewingPublicKey: `0x${bytesToHex(viewingPublicKey)}` as HexString,
|
|
363
|
+
derivationLabel: label,
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
this.privacyKeys = keys
|
|
367
|
+
return keys
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Check if privacy keys are derived
|
|
372
|
+
*/
|
|
373
|
+
hasPrivacyKeys(): boolean {
|
|
374
|
+
return this.privacyKeys !== null
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Get privacy keys
|
|
379
|
+
*/
|
|
380
|
+
getPrivacyKeys(): MyNearWalletPrivacyKeys | null {
|
|
381
|
+
return this.privacyKeys
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ─── Stealth Address Operations ─────────────────────────────────────────────
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Generate stealth meta-address
|
|
388
|
+
*/
|
|
389
|
+
generateStealthMetaAddress(label?: string): {
|
|
390
|
+
metaAddress: StealthMetaAddress
|
|
391
|
+
encoded: string
|
|
392
|
+
viewingPrivateKey: HexString
|
|
393
|
+
spendingPrivateKey: HexString
|
|
394
|
+
} {
|
|
395
|
+
if (!this.privacyKeys) {
|
|
396
|
+
throw new Error('Privacy keys not derived. Call derivePrivacyKeys first.')
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const metaAddress: StealthMetaAddress = {
|
|
400
|
+
chain: 'near',
|
|
401
|
+
spendingKey: this.privacyKeys.spendingPublicKey,
|
|
402
|
+
viewingKey: this.privacyKeys.viewingPublicKey,
|
|
403
|
+
label,
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const encoded = encodeNEARStealthMetaAddress(metaAddress)
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
metaAddress,
|
|
410
|
+
encoded,
|
|
411
|
+
viewingPrivateKey: this.privacyKeys.viewingPrivateKey,
|
|
412
|
+
spendingPrivateKey: this.privacyKeys.spendingPrivateKey,
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Generate stealth address for receiving
|
|
418
|
+
*/
|
|
419
|
+
generateStealthAddress(
|
|
420
|
+
metaAddress: string | StealthMetaAddress,
|
|
421
|
+
label?: string
|
|
422
|
+
): MyNearWalletStealthAddress {
|
|
423
|
+
const meta = typeof metaAddress === 'string'
|
|
424
|
+
? parseNEARStealthMetaAddress(metaAddress)
|
|
425
|
+
: metaAddress
|
|
426
|
+
|
|
427
|
+
const { stealthAddress, implicitAccountId } = generateNEARStealthAddress(meta)
|
|
428
|
+
|
|
429
|
+
const result: MyNearWalletStealthAddress = {
|
|
430
|
+
stealthAddress,
|
|
431
|
+
stealthAccountId: implicitAccountId,
|
|
432
|
+
ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
|
|
433
|
+
createdAt: Date.now(),
|
|
434
|
+
label,
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
this.stealthAddresses.set(implicitAccountId, result)
|
|
438
|
+
return result
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Check stealth address ownership
|
|
443
|
+
*/
|
|
444
|
+
checkStealthAddress(stealthAddress: StealthAddress): boolean {
|
|
445
|
+
if (!this.privacyKeys) {
|
|
446
|
+
throw new Error('Privacy keys not derived')
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return checkNEARStealthAddress(
|
|
450
|
+
stealthAddress,
|
|
451
|
+
this.privacyKeys.spendingPrivateKey,
|
|
452
|
+
this.privacyKeys.viewingPrivateKey
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Derive stealth private key
|
|
458
|
+
*/
|
|
459
|
+
deriveStealthPrivateKey(stealthAddress: StealthAddress): HexString {
|
|
460
|
+
if (!this.privacyKeys) {
|
|
461
|
+
throw new Error('Privacy keys not derived')
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const isOwner = this.checkStealthAddress(stealthAddress)
|
|
465
|
+
if (!isOwner) {
|
|
466
|
+
throw new Error('Stealth address does not belong to this wallet')
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const recovery = deriveNEARStealthPrivateKey(
|
|
470
|
+
stealthAddress,
|
|
471
|
+
this.privacyKeys.spendingPrivateKey,
|
|
472
|
+
this.privacyKeys.viewingPrivateKey
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
return recovery.privateKey
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// ─── Transaction Preview ────────────────────────────────────────────────────
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Preview a private transfer before signing
|
|
482
|
+
*/
|
|
483
|
+
previewPrivateTransfer(params: MyNearWalletPrivateTransferParams): TransactionPreview {
|
|
484
|
+
if (!this.accountId) {
|
|
485
|
+
throw new Error('Not connected to MyNearWallet')
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const recipientMeta = typeof params.recipientMetaAddress === 'string'
|
|
489
|
+
? parseNEARStealthMetaAddress(params.recipientMetaAddress)
|
|
490
|
+
: params.recipientMetaAddress
|
|
491
|
+
|
|
492
|
+
const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
|
|
493
|
+
const transfer = buildPrivateTransfer(recipientMeta, amount)
|
|
494
|
+
|
|
495
|
+
// Format amount in NEAR
|
|
496
|
+
const amountNEAR = formatNearAmount(amount)
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
senderId: this.accountId,
|
|
500
|
+
receiverId: transfer.stealthAccountId,
|
|
501
|
+
amountNEAR,
|
|
502
|
+
amountYocto: amount.toString(),
|
|
503
|
+
isPrivate: true,
|
|
504
|
+
stealthInfo: {
|
|
505
|
+
stealthAccountId: transfer.stealthAccountId,
|
|
506
|
+
announcementMemo: transfer.announcementMemo,
|
|
507
|
+
viewTag: transfer.stealthAddress.viewTag,
|
|
508
|
+
},
|
|
509
|
+
actions: transfer.actions.map((action) => ({
|
|
510
|
+
type: action.type,
|
|
511
|
+
params: serializeParams(action.params as unknown as Record<string, unknown>),
|
|
512
|
+
})),
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// ─── Private Transfers ──────────────────────────────────────────────────────
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Get URL for private transfer signing
|
|
520
|
+
*/
|
|
521
|
+
getPrivateTransferUrl(params: MyNearWalletPrivateTransferParams): string {
|
|
522
|
+
if (!this.accountId) {
|
|
523
|
+
throw new Error('Not connected to MyNearWallet')
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const recipientMeta = typeof params.recipientMetaAddress === 'string'
|
|
527
|
+
? parseNEARStealthMetaAddress(params.recipientMetaAddress)
|
|
528
|
+
: params.recipientMetaAddress
|
|
529
|
+
|
|
530
|
+
const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
|
|
531
|
+
const transfer = buildPrivateTransfer(recipientMeta, amount)
|
|
532
|
+
|
|
533
|
+
// Build transaction URL
|
|
534
|
+
const urlParams = new URLSearchParams({
|
|
535
|
+
signerId: this.accountId,
|
|
536
|
+
receiverId: transfer.stealthAccountId,
|
|
537
|
+
callbackUrl: this.config.callbackUrl,
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// Encode actions
|
|
541
|
+
const encodedActions = transfer.actions.map((action) => ({
|
|
542
|
+
type: action.type,
|
|
543
|
+
...serializeParams(action.params as unknown as Record<string, unknown>),
|
|
544
|
+
}))
|
|
545
|
+
|
|
546
|
+
urlParams.set('actions', JSON.stringify(encodedActions))
|
|
547
|
+
|
|
548
|
+
// Add privacy metadata
|
|
549
|
+
urlParams.set('meta', JSON.stringify({
|
|
550
|
+
isPrivate: true,
|
|
551
|
+
stealthAccountId: transfer.stealthAccountId,
|
|
552
|
+
announcementMemo: transfer.announcementMemo,
|
|
553
|
+
label: params.label,
|
|
554
|
+
}))
|
|
555
|
+
|
|
556
|
+
return `${this.walletUrl}/sign?${urlParams.toString()}`
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Send private transfer by redirecting to MyNearWallet
|
|
561
|
+
*/
|
|
562
|
+
sendPrivateTransfer(params: MyNearWalletPrivateTransferParams): void {
|
|
563
|
+
this.connectionState = 'signing'
|
|
564
|
+
|
|
565
|
+
if (typeof window !== 'undefined') {
|
|
566
|
+
window.location.href = this.getPrivateTransferUrl(params)
|
|
567
|
+
} else {
|
|
568
|
+
throw new Error('sendPrivateTransfer requires browser environment')
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Handle callback after signing
|
|
574
|
+
*/
|
|
575
|
+
handleTransactionCallback(callbackParams: URLSearchParams): MyNearWalletCallbackResult {
|
|
576
|
+
this.connectionState = 'connected'
|
|
577
|
+
|
|
578
|
+
const transactionHashes = callbackParams.get('transactionHashes') ?? undefined
|
|
579
|
+
const errorCode = callbackParams.get('errorCode') ?? undefined
|
|
580
|
+
const errorMessage = callbackParams.get('errorMessage') ?? undefined
|
|
581
|
+
|
|
582
|
+
return {
|
|
583
|
+
transactionHashes,
|
|
584
|
+
errorCode,
|
|
585
|
+
errorMessage,
|
|
586
|
+
accountId: this.accountId ?? undefined,
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// ─── Multi-Action Transactions ──────────────────────────────────────────────
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get URL for batch private transfers
|
|
594
|
+
*/
|
|
595
|
+
getBatchPrivateTransferUrl(
|
|
596
|
+
transfers: MyNearWalletPrivateTransferParams[]
|
|
597
|
+
): string {
|
|
598
|
+
if (!this.accountId) {
|
|
599
|
+
throw new Error('Not connected to MyNearWallet')
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Build all transactions
|
|
603
|
+
const transactions = transfers.map((params) => {
|
|
604
|
+
const recipientMeta = typeof params.recipientMetaAddress === 'string'
|
|
605
|
+
? parseNEARStealthMetaAddress(params.recipientMetaAddress)
|
|
606
|
+
: params.recipientMetaAddress
|
|
607
|
+
|
|
608
|
+
const amount = typeof params.amount === 'string' ? BigInt(params.amount) : params.amount
|
|
609
|
+
const transfer = buildPrivateTransfer(recipientMeta, amount)
|
|
610
|
+
|
|
611
|
+
return {
|
|
612
|
+
signerId: this.accountId,
|
|
613
|
+
receiverId: transfer.stealthAccountId,
|
|
614
|
+
actions: transfer.actions.map((action) => ({
|
|
615
|
+
type: action.type,
|
|
616
|
+
...serializeParams(action.params as unknown as Record<string, unknown>),
|
|
617
|
+
})),
|
|
618
|
+
meta: {
|
|
619
|
+
isPrivate: true,
|
|
620
|
+
stealthAccountId: transfer.stealthAccountId,
|
|
621
|
+
announcementMemo: transfer.announcementMemo,
|
|
622
|
+
label: params.label,
|
|
623
|
+
},
|
|
624
|
+
}
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
const urlParams = new URLSearchParams({
|
|
628
|
+
transactions: JSON.stringify(transactions),
|
|
629
|
+
callbackUrl: this.config.callbackUrl,
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
return `${this.walletUrl}/sign?${urlParams.toString()}`
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Send batch private transfers
|
|
637
|
+
*/
|
|
638
|
+
sendBatchPrivateTransfers(transfers: MyNearWalletPrivateTransferParams[]): void {
|
|
639
|
+
this.connectionState = 'signing'
|
|
640
|
+
|
|
641
|
+
if (typeof window !== 'undefined') {
|
|
642
|
+
window.location.href = this.getBatchPrivateTransferUrl(transfers)
|
|
643
|
+
} else {
|
|
644
|
+
throw new Error('sendBatchPrivateTransfers requires browser environment')
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// ─── Viewing Key Export ─────────────────────────────────────────────────────
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Export viewing key
|
|
652
|
+
*/
|
|
653
|
+
exportViewingKey(label?: string): MyNearWalletViewingKeyExport {
|
|
654
|
+
if (!this.privacyKeys) {
|
|
655
|
+
throw new Error('Privacy keys not derived')
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (!this.accountId) {
|
|
659
|
+
throw new Error('Not connected')
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return {
|
|
663
|
+
network: this.config.network,
|
|
664
|
+
viewingPublicKey: this.privacyKeys.viewingPublicKey,
|
|
665
|
+
viewingPrivateKey: this.privacyKeys.viewingPrivateKey,
|
|
666
|
+
spendingPublicKey: this.privacyKeys.spendingPublicKey,
|
|
667
|
+
accountId: this.accountId,
|
|
668
|
+
createdAt: Date.now(),
|
|
669
|
+
label,
|
|
670
|
+
walletType: 'mynearwallet',
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// ─── Utility Methods ────────────────────────────────────────────────────────
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Get tracked stealth addresses
|
|
678
|
+
*/
|
|
679
|
+
getStealthAddresses(): Map<string, MyNearWalletStealthAddress> {
|
|
680
|
+
return new Map(this.stealthAddresses)
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Get wallet URL
|
|
685
|
+
*/
|
|
686
|
+
getWalletUrl(): string {
|
|
687
|
+
return this.walletUrl
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Get config
|
|
692
|
+
*/
|
|
693
|
+
getConfig(): MyNearWalletConfig {
|
|
694
|
+
return { ...this.config }
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// ─── Factory Functions ────────────────────────────────────────────────────────
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Create MyNearWallet privacy integration
|
|
702
|
+
*/
|
|
703
|
+
export function createMyNearWalletPrivacy(
|
|
704
|
+
config: MyNearWalletConfig
|
|
705
|
+
): MyNearWalletPrivacy {
|
|
706
|
+
return new MyNearWalletPrivacy(config)
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Create mainnet MyNearWallet integration
|
|
711
|
+
*/
|
|
712
|
+
export function createMainnetMyNearWallet(
|
|
713
|
+
callbackUrl: string
|
|
714
|
+
): MyNearWalletPrivacy {
|
|
715
|
+
return new MyNearWalletPrivacy({
|
|
716
|
+
network: 'mainnet',
|
|
717
|
+
callbackUrl,
|
|
718
|
+
})
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Create testnet MyNearWallet integration
|
|
723
|
+
*/
|
|
724
|
+
export function createTestnetMyNearWallet(
|
|
725
|
+
callbackUrl: string
|
|
726
|
+
): MyNearWalletPrivacy {
|
|
727
|
+
return new MyNearWalletPrivacy({
|
|
728
|
+
network: 'testnet',
|
|
729
|
+
callbackUrl,
|
|
730
|
+
})
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// ─── Utility Functions ────────────────────────────────────────────────────────
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Clamp scalar for ed25519
|
|
737
|
+
*/
|
|
738
|
+
function clampScalar(bytes: Uint8Array): Uint8Array {
|
|
739
|
+
const clamped = new Uint8Array(bytes)
|
|
740
|
+
clamped[0] &= 248
|
|
741
|
+
clamped[31] &= 127
|
|
742
|
+
clamped[31] |= 64
|
|
743
|
+
return clamped
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Format amount in NEAR
|
|
748
|
+
*/
|
|
749
|
+
function formatNearAmount(yoctoNear: bigint): string {
|
|
750
|
+
const nearStr = yoctoNear.toString().padStart(25, '0')
|
|
751
|
+
const whole = nearStr.slice(0, -24) || '0'
|
|
752
|
+
const decimal = nearStr.slice(-24).replace(/0+$/, '')
|
|
753
|
+
return decimal ? `${whole}.${decimal}` : whole
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Serialize action params for URL encoding
|
|
758
|
+
*/
|
|
759
|
+
function serializeParams(params: Record<string, unknown>): Record<string, unknown> {
|
|
760
|
+
const serialized: Record<string, unknown> = {}
|
|
761
|
+
|
|
762
|
+
for (const [key, value] of Object.entries(params)) {
|
|
763
|
+
if (typeof value === 'bigint') {
|
|
764
|
+
serialized[key] = value.toString()
|
|
765
|
+
} else if (value instanceof Uint8Array) {
|
|
766
|
+
serialized[key] = bytesToHex(value)
|
|
767
|
+
} else {
|
|
768
|
+
serialized[key] = value
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
return serialized
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Parse callback URL parameters
|
|
777
|
+
*/
|
|
778
|
+
export function parseMyNearWalletCallback(
|
|
779
|
+
url: string
|
|
780
|
+
): { type: 'login' | 'transaction'; params: URLSearchParams } {
|
|
781
|
+
const urlObj = new URL(url)
|
|
782
|
+
const params = urlObj.searchParams
|
|
783
|
+
|
|
784
|
+
// Check if login or transaction callback
|
|
785
|
+
if (params.has('account_id')) {
|
|
786
|
+
return { type: 'login', params }
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
return { type: 'transaction', params }
|
|
790
|
+
}
|