@noir-wallet/sdk 0.1.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 +327 -0
- package/dist/chains/zcash/index.d.mts +65 -0
- package/dist/chains/zcash/index.d.ts +65 -0
- package/dist/chains/zcash/index.js +221 -0
- package/dist/chains/zcash/index.mjs +14 -0
- package/dist/chunk-B5WLNS6I.mjs +121 -0
- package/dist/chunk-JG4K44MD.mjs +183 -0
- package/dist/chunk-JTGVB6AM.mjs +41 -0
- package/dist/chunk-LM5EFW23.mjs +173 -0
- package/dist/chunk-OKXWHTTZ.mjs +163 -0
- package/dist/chunk-SOSIUE6V.mjs +40 -0
- package/dist/chunk-SUNMYR5E.mjs +163 -0
- package/dist/chunk-VDR6IC34.mjs +93 -0
- package/dist/chunk-XUNZPMTF.mjs +146 -0
- package/dist/chunk-YNMF6UCO.mjs +90 -0
- package/dist/chunk-ZSM65CPQ.mjs +90 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +239 -0
- package/dist/index.mjs +30 -0
- package/dist/provider-DE7vB7SX.d.mts +48 -0
- package/dist/provider-DE7vB7SX.d.ts +48 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# @noir-wallet/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for integrating with Noir Wallet Chrome Extension.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @noir-wallet/sdk
|
|
9
|
+
# or
|
|
10
|
+
yarn add @noir-wallet/sdk
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @noir-wallet/sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic Example
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { getNoirWallet } from '@noir-wallet/sdk'
|
|
21
|
+
|
|
22
|
+
// Get Noir Wallet
|
|
23
|
+
const noirWallet = getNoirWallet()
|
|
24
|
+
if (!noirWallet) {
|
|
25
|
+
throw new Error('Noir Wallet not installed')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const zcash = noirWallet.zcash
|
|
29
|
+
|
|
30
|
+
// Check existing connection (silent, no popup)
|
|
31
|
+
const accounts = await zcash.getAccounts()
|
|
32
|
+
|
|
33
|
+
// Connect wallet if not connected (shows popup)
|
|
34
|
+
if (!accounts) {
|
|
35
|
+
const newAccounts = await zcash.connect()
|
|
36
|
+
console.log('Wallet connected:', newAccounts)
|
|
37
|
+
} else {
|
|
38
|
+
console.log('Already connected:', accounts)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get balance
|
|
42
|
+
const balance = await zcash.getBalance()
|
|
43
|
+
console.log('Transparent:', balance.transparent, 'ZEC')
|
|
44
|
+
console.log('Shielded:', balance.shielded, 'ZEC')
|
|
45
|
+
console.log('Available:', balance.available, 'ZEC') // Precise transferable amount
|
|
46
|
+
|
|
47
|
+
// Get public key
|
|
48
|
+
const publicKeyInfo = await zcash.getPublicKey()
|
|
49
|
+
if (publicKeyInfo) {
|
|
50
|
+
console.log('Public Key:', publicKeyInfo.pubkey)
|
|
51
|
+
console.log('Address:', publicKeyInfo.address)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Send transaction (uses shielded balance only)
|
|
55
|
+
const txid = await zcash.sendTransaction({
|
|
56
|
+
to: 'zs1XYZ...',
|
|
57
|
+
amount: '0.1'
|
|
58
|
+
})
|
|
59
|
+
console.log('Transaction sent:', txid)
|
|
60
|
+
|
|
61
|
+
// Sign message
|
|
62
|
+
const result = await zcash.signMessage('Hello World')
|
|
63
|
+
console.log('Signature:', result.signature)
|
|
64
|
+
console.log('Address:', result.address)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Detect Provider
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { getNoirWallet, isNoirWalletInstalled } from '@noir-wallet/sdk'
|
|
71
|
+
|
|
72
|
+
// Check if installed
|
|
73
|
+
if (isNoirWalletInstalled()) {
|
|
74
|
+
const noirWallet = getNoirWallet()
|
|
75
|
+
console.log('Noir Wallet detected')
|
|
76
|
+
} else {
|
|
77
|
+
console.error('Noir Wallet not found')
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Event Listeners
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const noirWallet = getNoirWallet()
|
|
85
|
+
const zcash = noirWallet.zcash
|
|
86
|
+
|
|
87
|
+
// Connect first
|
|
88
|
+
await zcash.connect()
|
|
89
|
+
|
|
90
|
+
// Listen to account changes (unlock/lock, switch account)
|
|
91
|
+
zcash.on('accountsChanged', accounts => {
|
|
92
|
+
console.log('Accounts changed:', accounts)
|
|
93
|
+
if (accounts.length === 0) {
|
|
94
|
+
console.log('Wallet locked or disconnected')
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
// Listen to chain/network changes
|
|
99
|
+
zcash.on('chainChanged', chainInfo => {
|
|
100
|
+
console.log('Network changed:', chainInfo)
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## API
|
|
105
|
+
|
|
106
|
+
### Methods
|
|
107
|
+
|
|
108
|
+
All methods are available on `noirWallet.zcash`:
|
|
109
|
+
|
|
110
|
+
#### `connect()`
|
|
111
|
+
|
|
112
|
+
Request wallet connection (shows popup if not authorized).
|
|
113
|
+
|
|
114
|
+
**Returns**: `Promise<ZcashAddress>` - Address object with transparent and shielded addresses
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const accounts = await zcash.connect()
|
|
118
|
+
console.log('Transparent:', accounts.transparent)
|
|
119
|
+
console.log('Shielded:', accounts.shielded)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### `getAccounts()`
|
|
123
|
+
|
|
124
|
+
Query existing connection silently (no popup).
|
|
125
|
+
|
|
126
|
+
**Returns**: `Promise<ZcashAddress | null>` - Address object if connected, null if not connected
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const accounts = await zcash.getAccounts()
|
|
130
|
+
if (accounts) {
|
|
131
|
+
console.log('Connected:', accounts.transparent)
|
|
132
|
+
} else {
|
|
133
|
+
console.log('Not connected')
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### `getBalance()`
|
|
138
|
+
|
|
139
|
+
Get wallet balance.
|
|
140
|
+
|
|
141
|
+
**Returns**: `Promise<Balance>`
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const balance = await zcash.getBalance()
|
|
145
|
+
console.log('Shielded:', balance.shielded, 'ZEC')
|
|
146
|
+
console.log('Available:', balance.available, 'ZEC') // Recommended for max send amount
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Balance fields**:
|
|
150
|
+
|
|
151
|
+
- `transparent`: Transparent address balance
|
|
152
|
+
- `shielded`: Shielded balance (Sapling + Orchard)
|
|
153
|
+
- `total`: Total balance (transparent + shielded)
|
|
154
|
+
- `available`: **Precise transferable amount** - Maximum amount that can be sent considering UTXO selection, dynamic fees, and dust threshold. Calculated during background sync using WASM's `get_max_transferable_amount` method.
|
|
155
|
+
|
|
156
|
+
#### `getPublicKey()`
|
|
157
|
+
|
|
158
|
+
Get the public key of the transparent address.
|
|
159
|
+
|
|
160
|
+
**Returns**: `Promise<{ pubkey: string, address: string } | null>` - Public key info if connected and unlocked, null if locked
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
const publicKeyInfo = await zcash.getPublicKey()
|
|
164
|
+
if (publicKeyInfo) {
|
|
165
|
+
console.log('Public Key:', publicKeyInfo.pubkey)
|
|
166
|
+
console.log('Address:', publicKeyInfo.address)
|
|
167
|
+
} else {
|
|
168
|
+
console.log('Wallet is locked')
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Note**: This method requires the wallet to be connected but does not trigger an unlock popup. Returns `null` if the wallet is locked.
|
|
173
|
+
|
|
174
|
+
#### `sendTransaction(params)`
|
|
175
|
+
|
|
176
|
+
Send a transaction. **Only shielded balance is used for sending.** Transparent balance cannot be spent directly — it must be shielded in the wallet first. Memo is not yet supported.
|
|
177
|
+
|
|
178
|
+
**Params**:
|
|
179
|
+
|
|
180
|
+
- `to: string` - Recipient address
|
|
181
|
+
- `amount: string` - Amount in ZEC (deducted from shielded balance)
|
|
182
|
+
|
|
183
|
+
**Returns**: `Promise<string>` - Transaction ID
|
|
184
|
+
|
|
185
|
+
> **Note:** All sends use shielded balance. If you have transparent balance, please shield it in the wallet first.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const txid = await zcash.sendTransaction({
|
|
189
|
+
to: 'zs1XYZ...',
|
|
190
|
+
amount: '0.1'
|
|
191
|
+
})
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### `signMessage(message)`
|
|
195
|
+
|
|
196
|
+
Sign a message with the transparent address.
|
|
197
|
+
|
|
198
|
+
**Params**: `message: string` - Message to sign
|
|
199
|
+
|
|
200
|
+
**Returns**: `Promise<{ signature: string, pubkey: string, address: string }>`
|
|
201
|
+
|
|
202
|
+
- `signature`: Hex-encoded ECDSA signature
|
|
203
|
+
- `pubkey`: Hex-encoded public key
|
|
204
|
+
- `address`: Transparent address used for signing
|
|
205
|
+
|
|
206
|
+
**Note**: Message signing currently only supports transparent addresses.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const result = await zcash.signMessage('Hello World')
|
|
210
|
+
console.log('Signature:', result.signature)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### `switchNetwork(network)`
|
|
214
|
+
|
|
215
|
+
Switch between mainnet and testnet.
|
|
216
|
+
|
|
217
|
+
**Params**: `network: 'mainnet' | 'testnet'`
|
|
218
|
+
|
|
219
|
+
**Returns**: `Promise<boolean>`
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
await zcash.switchNetwork('testnet')
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Utility Functions
|
|
226
|
+
|
|
227
|
+
#### `publicKeyToAddress(pubkey, network)`
|
|
228
|
+
|
|
229
|
+
Convert a public key to a Zcash transparent address.
|
|
230
|
+
|
|
231
|
+
**Params**:
|
|
232
|
+
|
|
233
|
+
- `pubkey: string` - Public key in hexadecimal format (compressed 33 bytes or uncompressed 65 bytes)
|
|
234
|
+
- `network: 'mainnet' | 'testnet'` - Network type (defaults to 'mainnet')
|
|
235
|
+
|
|
236
|
+
**Returns**: `string` - Zcash transparent address (P2PKH format)
|
|
237
|
+
|
|
238
|
+
**Throws**: Error if public key format is invalid
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { publicKeyToAddress } from '@noir-wallet/sdk'
|
|
242
|
+
|
|
243
|
+
// Get public key from wallet
|
|
244
|
+
const { pubkey } = await zcash.getPublicKey()
|
|
245
|
+
|
|
246
|
+
// Convert to address for verification
|
|
247
|
+
const address = publicKeyToAddress(pubkey, 'mainnet')
|
|
248
|
+
console.log('Address:', address)
|
|
249
|
+
|
|
250
|
+
// Convert external public key
|
|
251
|
+
const externalPubkey = '03a1b2c3d4e5f6...'
|
|
252
|
+
const externalAddress = publicKeyToAddress(externalPubkey, 'mainnet')
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Public Key Formats**:
|
|
256
|
+
|
|
257
|
+
- Compressed (33 bytes): Starts with `02` or `03`
|
|
258
|
+
- Uncompressed (65 bytes): Starts with `04`
|
|
259
|
+
|
|
260
|
+
**Note**: This function implements the Bitcoin/Zcash P2PKH address generation algorithm (SHA256 → RIPEMD160 → Base58Check).
|
|
261
|
+
|
|
262
|
+
### Events
|
|
263
|
+
|
|
264
|
+
#### `accountsChanged`
|
|
265
|
+
|
|
266
|
+
Triggered when accounts change (unlock/lock, switch account).
|
|
267
|
+
|
|
268
|
+
**Data**: `ZcashAddress | null` - Current addresses (null if locked/disconnected)
|
|
269
|
+
|
|
270
|
+
#### `chainChanged`
|
|
271
|
+
|
|
272
|
+
Triggered when network changes.
|
|
273
|
+
|
|
274
|
+
**Data**: `{ chainId: string, network: string }`
|
|
275
|
+
|
|
276
|
+
## Types
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
interface ZcashAddress {
|
|
280
|
+
transparent: string
|
|
281
|
+
shielded: string
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
interface Balance {
|
|
285
|
+
transparent: string
|
|
286
|
+
shielded: string
|
|
287
|
+
total?: string
|
|
288
|
+
available?: string // Precise max transferable amount
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
interface SendTransactionParams {
|
|
292
|
+
to: string
|
|
293
|
+
amount: string
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
interface SignMessageResult {
|
|
297
|
+
signature: string // Hex-encoded ECDSA signature
|
|
298
|
+
pubkey: string // Hex-encoded public key
|
|
299
|
+
address: string // Transparent address used for signing
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
type Network = 'mainnet' | 'testnet'
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Error Handling
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
const noirWallet = getNoirWallet()
|
|
309
|
+
if (!noirWallet) {
|
|
310
|
+
console.error('Please install Noir Wallet extension')
|
|
311
|
+
return
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
await noirWallet.zcash.connect()
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (error.code === 4001) {
|
|
318
|
+
console.error('User rejected the request')
|
|
319
|
+
} else {
|
|
320
|
+
console.error('Connection failed:', error.message)
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## License
|
|
326
|
+
|
|
327
|
+
MIT
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
interface ZcashProvider {
|
|
2
|
+
request(args: RequestArguments): Promise<any>;
|
|
3
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
4
|
+
removeListener?(event: string, handler: (...args: any[]) => void): void;
|
|
5
|
+
disconnect(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
interface RequestArguments {
|
|
8
|
+
method: string;
|
|
9
|
+
params?: any[];
|
|
10
|
+
}
|
|
11
|
+
interface ZcashAddress {
|
|
12
|
+
transparent: string;
|
|
13
|
+
shielded: string;
|
|
14
|
+
}
|
|
15
|
+
interface Balance {
|
|
16
|
+
transparent: string;
|
|
17
|
+
shielded: string;
|
|
18
|
+
total?: string;
|
|
19
|
+
available?: string;
|
|
20
|
+
}
|
|
21
|
+
interface SendTransactionParams {
|
|
22
|
+
to: string;
|
|
23
|
+
amount: string;
|
|
24
|
+
}
|
|
25
|
+
interface TransactionReceipt {
|
|
26
|
+
txid: string;
|
|
27
|
+
from: string;
|
|
28
|
+
to: string;
|
|
29
|
+
amount: string;
|
|
30
|
+
type: 'transparent' | 'shielded';
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
interface SignMessageResult {
|
|
34
|
+
signature: string;
|
|
35
|
+
pubkey: string;
|
|
36
|
+
address: string;
|
|
37
|
+
}
|
|
38
|
+
type Network$1 = 'mainnet' | 'testnet';
|
|
39
|
+
|
|
40
|
+
declare class ZcashAPI {
|
|
41
|
+
private provider;
|
|
42
|
+
constructor(provider: ZcashProvider);
|
|
43
|
+
connect(): Promise<ZcashAddress>;
|
|
44
|
+
getAccounts(): Promise<ZcashAddress | null>;
|
|
45
|
+
getBalance(): Promise<Balance>;
|
|
46
|
+
getPublicKey(): Promise<{
|
|
47
|
+
pubkey: string;
|
|
48
|
+
address: string;
|
|
49
|
+
} | null>;
|
|
50
|
+
sendTransaction(params: SendTransactionParams): Promise<string>;
|
|
51
|
+
signMessage(message: string): Promise<SignMessageResult>;
|
|
52
|
+
switchNetwork(network: Network$1): Promise<boolean>;
|
|
53
|
+
disconnect(): Promise<void>;
|
|
54
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
55
|
+
removeListener(event: string, handler: (...args: any[]) => void): void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare function getZcashProvider(): ZcashProvider | null;
|
|
59
|
+
declare function detectProvider(timeout?: number): Promise<ZcashProvider>;
|
|
60
|
+
declare function getProvider(): ZcashProvider | null;
|
|
61
|
+
|
|
62
|
+
type Network = 'mainnet' | 'testnet';
|
|
63
|
+
declare function publicKeyToAddress(pubkeyHex: string, network?: Network): string;
|
|
64
|
+
|
|
65
|
+
export { type Balance, type Network$1 as Network, type RequestArguments, type SendTransactionParams, type SignMessageResult, type TransactionReceipt, ZcashAPI, type ZcashAddress, type ZcashProvider, detectProvider, getProvider, getZcashProvider, publicKeyToAddress };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
interface ZcashProvider {
|
|
2
|
+
request(args: RequestArguments): Promise<any>;
|
|
3
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
4
|
+
removeListener?(event: string, handler: (...args: any[]) => void): void;
|
|
5
|
+
disconnect(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
interface RequestArguments {
|
|
8
|
+
method: string;
|
|
9
|
+
params?: any[];
|
|
10
|
+
}
|
|
11
|
+
interface ZcashAddress {
|
|
12
|
+
transparent: string;
|
|
13
|
+
shielded: string;
|
|
14
|
+
}
|
|
15
|
+
interface Balance {
|
|
16
|
+
transparent: string;
|
|
17
|
+
shielded: string;
|
|
18
|
+
total?: string;
|
|
19
|
+
available?: string;
|
|
20
|
+
}
|
|
21
|
+
interface SendTransactionParams {
|
|
22
|
+
to: string;
|
|
23
|
+
amount: string;
|
|
24
|
+
}
|
|
25
|
+
interface TransactionReceipt {
|
|
26
|
+
txid: string;
|
|
27
|
+
from: string;
|
|
28
|
+
to: string;
|
|
29
|
+
amount: string;
|
|
30
|
+
type: 'transparent' | 'shielded';
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
interface SignMessageResult {
|
|
34
|
+
signature: string;
|
|
35
|
+
pubkey: string;
|
|
36
|
+
address: string;
|
|
37
|
+
}
|
|
38
|
+
type Network$1 = 'mainnet' | 'testnet';
|
|
39
|
+
|
|
40
|
+
declare class ZcashAPI {
|
|
41
|
+
private provider;
|
|
42
|
+
constructor(provider: ZcashProvider);
|
|
43
|
+
connect(): Promise<ZcashAddress>;
|
|
44
|
+
getAccounts(): Promise<ZcashAddress | null>;
|
|
45
|
+
getBalance(): Promise<Balance>;
|
|
46
|
+
getPublicKey(): Promise<{
|
|
47
|
+
pubkey: string;
|
|
48
|
+
address: string;
|
|
49
|
+
} | null>;
|
|
50
|
+
sendTransaction(params: SendTransactionParams): Promise<string>;
|
|
51
|
+
signMessage(message: string): Promise<SignMessageResult>;
|
|
52
|
+
switchNetwork(network: Network$1): Promise<boolean>;
|
|
53
|
+
disconnect(): Promise<void>;
|
|
54
|
+
on(event: string, handler: (...args: any[]) => void): void;
|
|
55
|
+
removeListener(event: string, handler: (...args: any[]) => void): void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare function getZcashProvider(): ZcashProvider | null;
|
|
59
|
+
declare function detectProvider(timeout?: number): Promise<ZcashProvider>;
|
|
60
|
+
declare function getProvider(): ZcashProvider | null;
|
|
61
|
+
|
|
62
|
+
type Network = 'mainnet' | 'testnet';
|
|
63
|
+
declare function publicKeyToAddress(pubkeyHex: string, network?: Network): string;
|
|
64
|
+
|
|
65
|
+
export { type Balance, type Network$1 as Network, type RequestArguments, type SendTransactionParams, type SignMessageResult, type TransactionReceipt, ZcashAPI, type ZcashAddress, type ZcashProvider, detectProvider, getProvider, getZcashProvider, publicKeyToAddress };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
|
+
|
|
32
|
+
// src/chains/zcash/index.ts
|
|
33
|
+
var zcash_exports = {};
|
|
34
|
+
__export(zcash_exports, {
|
|
35
|
+
ZcashAPI: () => ZcashAPI,
|
|
36
|
+
detectProvider: () => detectProvider,
|
|
37
|
+
getProvider: () => getProvider,
|
|
38
|
+
getZcashProvider: () => getZcashProvider,
|
|
39
|
+
publicKeyToAddress: () => publicKeyToAddress
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(zcash_exports);
|
|
42
|
+
|
|
43
|
+
// src/chains/zcash/provider.ts
|
|
44
|
+
function getZcashProvider() {
|
|
45
|
+
if (typeof window === "undefined") return null;
|
|
46
|
+
const rheaWallet = window.rheawallet;
|
|
47
|
+
return rheaWallet?.zcash || null;
|
|
48
|
+
}
|
|
49
|
+
async function detectProvider(timeout = 3e3) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
if (typeof window === "undefined") {
|
|
52
|
+
return reject(new Error("window is undefined"));
|
|
53
|
+
}
|
|
54
|
+
const provider = getZcashProvider();
|
|
55
|
+
if (provider) {
|
|
56
|
+
return resolve(provider);
|
|
57
|
+
}
|
|
58
|
+
let handled = false;
|
|
59
|
+
const handleProvider = () => {
|
|
60
|
+
if (handled) return;
|
|
61
|
+
handled = true;
|
|
62
|
+
const provider2 = getZcashProvider();
|
|
63
|
+
if (provider2) {
|
|
64
|
+
resolve(provider2);
|
|
65
|
+
} else {
|
|
66
|
+
reject(new Error("RHEA Wallet is not installed"));
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
window.addEventListener("rheawallet#initialized", handleProvider, { once: true });
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
handleProvider();
|
|
72
|
+
}, timeout);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function getProvider() {
|
|
76
|
+
return getZcashProvider();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/chains/zcash/api.ts
|
|
80
|
+
var ZcashAPI = class {
|
|
81
|
+
constructor(provider) {
|
|
82
|
+
__publicField(this, "provider");
|
|
83
|
+
this.provider = provider;
|
|
84
|
+
}
|
|
85
|
+
async connect() {
|
|
86
|
+
return this.provider.request({ method: "zcash_requestAccounts" });
|
|
87
|
+
}
|
|
88
|
+
async getAccounts() {
|
|
89
|
+
return this.provider.request({ method: "zcash_getAccounts" });
|
|
90
|
+
}
|
|
91
|
+
async getBalance() {
|
|
92
|
+
return this.provider.request({ method: "zcash_getBalance" });
|
|
93
|
+
}
|
|
94
|
+
async getPublicKey() {
|
|
95
|
+
return this.provider.request({ method: "zcash_getPublicKey" });
|
|
96
|
+
}
|
|
97
|
+
async sendTransaction(params) {
|
|
98
|
+
return this.provider.request({
|
|
99
|
+
method: "zcash_sendTransaction",
|
|
100
|
+
params: [params]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async signMessage(message) {
|
|
104
|
+
return this.provider.request({
|
|
105
|
+
method: "zcash_signMessage",
|
|
106
|
+
params: [message]
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async switchNetwork(network) {
|
|
110
|
+
return this.provider.request({
|
|
111
|
+
method: "zcash_switchNetwork",
|
|
112
|
+
params: [{ network }]
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async disconnect() {
|
|
116
|
+
await this.provider.request({ method: "zcash_disconnect" });
|
|
117
|
+
}
|
|
118
|
+
on(event, handler) {
|
|
119
|
+
this.provider.on(event, handler);
|
|
120
|
+
}
|
|
121
|
+
removeListener(event, handler) {
|
|
122
|
+
this.provider.removeListener?.(event, handler);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// src/chains/zcash/utils.ts
|
|
127
|
+
var import_bs58 = __toESM(require("bs58"));
|
|
128
|
+
var hashjs = __toESM(require("hash.js"));
|
|
129
|
+
var MAINNET_P2PKH_PREFIX = new Uint8Array([28, 184]);
|
|
130
|
+
var TESTNET_P2PKH_PREFIX = new Uint8Array([29, 37]);
|
|
131
|
+
function sha2562(data) {
|
|
132
|
+
return new Uint8Array(hashjs.sha256().update(Array.from(data)).digest());
|
|
133
|
+
}
|
|
134
|
+
function ripemd1602(data) {
|
|
135
|
+
return new Uint8Array(hashjs.ripemd160().update(Array.from(data)).digest());
|
|
136
|
+
}
|
|
137
|
+
function hash160(data) {
|
|
138
|
+
return ripemd1602(sha2562(data));
|
|
139
|
+
}
|
|
140
|
+
function hexToUint8Array(hex) {
|
|
141
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
142
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
143
|
+
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
|
|
144
|
+
}
|
|
145
|
+
return bytes;
|
|
146
|
+
}
|
|
147
|
+
function concatUint8Arrays(...arrays) {
|
|
148
|
+
const totalLength = arrays.reduce((acc, arr) => acc + arr.length, 0);
|
|
149
|
+
const result = new Uint8Array(totalLength);
|
|
150
|
+
let offset = 0;
|
|
151
|
+
for (const arr of arrays) {
|
|
152
|
+
result.set(arr, offset);
|
|
153
|
+
offset += arr.length;
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
function compressPublicKey(pubkey) {
|
|
158
|
+
if (pubkey.length === 33) {
|
|
159
|
+
return pubkey;
|
|
160
|
+
}
|
|
161
|
+
if (pubkey.length !== 65) {
|
|
162
|
+
throw new Error("Invalid public key length for compression");
|
|
163
|
+
}
|
|
164
|
+
if (pubkey[0] !== 4) {
|
|
165
|
+
throw new Error("Invalid uncompressed public key format");
|
|
166
|
+
}
|
|
167
|
+
const x = pubkey.slice(1, 33);
|
|
168
|
+
const y = pubkey.slice(33, 65);
|
|
169
|
+
const yIsOdd = (y[y.length - 1] & 1) === 1;
|
|
170
|
+
const prefix = yIsOdd ? 3 : 2;
|
|
171
|
+
const compressed = new Uint8Array(33);
|
|
172
|
+
compressed[0] = prefix;
|
|
173
|
+
compressed.set(x, 1);
|
|
174
|
+
return compressed;
|
|
175
|
+
}
|
|
176
|
+
function publicKeyToAddress(pubkeyHex, network = "mainnet") {
|
|
177
|
+
if (!pubkeyHex || typeof pubkeyHex !== "string") {
|
|
178
|
+
throw new Error("Invalid public key: must be a non-empty hex string");
|
|
179
|
+
}
|
|
180
|
+
const cleanHex = pubkeyHex.toLowerCase().replace(/^0x/, "");
|
|
181
|
+
if (!/^[0-9a-f]+$/.test(cleanHex)) {
|
|
182
|
+
throw new Error("Invalid public key: must contain only hexadecimal characters");
|
|
183
|
+
}
|
|
184
|
+
const pubkeyBytes = hexToUint8Array(cleanHex);
|
|
185
|
+
if (pubkeyBytes.length !== 33 && pubkeyBytes.length !== 65) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`Invalid public key length: expected 33 (compressed) or 65 (uncompressed) bytes, got ${pubkeyBytes.length}`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (pubkeyBytes.length === 33) {
|
|
191
|
+
const prefix = pubkeyBytes[0];
|
|
192
|
+
if (prefix !== 2 && prefix !== 3) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Invalid compressed public key prefix: expected 0x02 or 0x03, got 0x${prefix.toString(16).padStart(2, "0")}`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
} else if (pubkeyBytes.length === 65) {
|
|
198
|
+
const prefix = pubkeyBytes[0];
|
|
199
|
+
if (prefix !== 4) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Invalid uncompressed public key prefix: expected 0x04, got 0x${prefix.toString(16).padStart(2, "0")}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const compressedPubkey = compressPublicKey(pubkeyBytes);
|
|
206
|
+
const pubkeyHash = hash160(compressedPubkey);
|
|
207
|
+
const versionPrefix = network === "mainnet" ? MAINNET_P2PKH_PREFIX : TESTNET_P2PKH_PREFIX;
|
|
208
|
+
const payload = concatUint8Arrays(versionPrefix, pubkeyHash);
|
|
209
|
+
const checksum = sha2562(sha2562(payload)).slice(0, 4);
|
|
210
|
+
const addressBytes = concatUint8Arrays(payload, checksum);
|
|
211
|
+
const address = import_bs58.default.encode(addressBytes);
|
|
212
|
+
return address;
|
|
213
|
+
}
|
|
214
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
215
|
+
0 && (module.exports = {
|
|
216
|
+
ZcashAPI,
|
|
217
|
+
detectProvider,
|
|
218
|
+
getProvider,
|
|
219
|
+
getZcashProvider,
|
|
220
|
+
publicKeyToAddress
|
|
221
|
+
});
|