@bytezhang/hardware-wallet-core 0.0.1
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/dist/index.d.mts +822 -0
- package/dist/index.d.ts +822 -0
- package/dist/index.js +328 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +289 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +48 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
declare enum HardwareErrorCode {
|
|
2
|
+
UnknownError = 0,
|
|
3
|
+
DeviceNotFound = 1,
|
|
4
|
+
DeviceDisconnected = 2,
|
|
5
|
+
UserRejected = 3,
|
|
6
|
+
DeviceBusy = 4,
|
|
7
|
+
FirmwareUpdateRequired = 5,
|
|
8
|
+
AppNotOpen = 6,
|
|
9
|
+
InvalidParams = 7,
|
|
10
|
+
TransportError = 8,
|
|
11
|
+
OperationTimeout = 9,
|
|
12
|
+
MethodNotSupported = 10,
|
|
13
|
+
PinInvalid = 5520,
|
|
14
|
+
PinCancelled = 5521,
|
|
15
|
+
PassphraseRejected = 5522,
|
|
16
|
+
DeviceLocked = 5530,
|
|
17
|
+
DeviceNotInitialized = 5531,
|
|
18
|
+
DeviceInBootloader = 5532,
|
|
19
|
+
FirmwareTooOld = 5533,
|
|
20
|
+
WrongApp = 5540,
|
|
21
|
+
BridgeNotFound = 5550,
|
|
22
|
+
TransportNotAvailable = 5551
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface Success<T> {
|
|
26
|
+
success: true;
|
|
27
|
+
payload: T;
|
|
28
|
+
}
|
|
29
|
+
interface Failure {
|
|
30
|
+
success: false;
|
|
31
|
+
payload: {
|
|
32
|
+
error: string;
|
|
33
|
+
code: HardwareErrorCode;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
type Response<T> = Success<T> | Failure;
|
|
37
|
+
declare function success<T>(payload: T): Success<T>;
|
|
38
|
+
declare function failure(code: HardwareErrorCode, error: string): Failure;
|
|
39
|
+
|
|
40
|
+
type VendorType = 'trezor' | 'ledger' | 'keystone' | 'keystoneqr';
|
|
41
|
+
type ConnectionType = 'usb' | 'ble' | 'qr';
|
|
42
|
+
type TransportType = 'usb' | 'ble' | 'hid' | 'bridge' | 'qr';
|
|
43
|
+
interface DeviceInfo {
|
|
44
|
+
vendor: VendorType;
|
|
45
|
+
model: string;
|
|
46
|
+
firmwareVersion: string;
|
|
47
|
+
deviceId: string;
|
|
48
|
+
connectId: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
connectionType: ConnectionType;
|
|
51
|
+
battery?: number;
|
|
52
|
+
}
|
|
53
|
+
interface DeviceTarget {
|
|
54
|
+
connectId: string;
|
|
55
|
+
deviceId: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface EvmGetAddressParams {
|
|
59
|
+
path: string;
|
|
60
|
+
showOnDevice?: boolean;
|
|
61
|
+
chainId?: number;
|
|
62
|
+
}
|
|
63
|
+
interface EvmAddress {
|
|
64
|
+
address: string;
|
|
65
|
+
path: string;
|
|
66
|
+
}
|
|
67
|
+
interface EvmGetPublicKeyParams {
|
|
68
|
+
path: string;
|
|
69
|
+
showOnDevice?: boolean;
|
|
70
|
+
}
|
|
71
|
+
interface EvmPublicKey {
|
|
72
|
+
publicKey: string;
|
|
73
|
+
path: string;
|
|
74
|
+
}
|
|
75
|
+
interface EvmSignTxParams {
|
|
76
|
+
path: string;
|
|
77
|
+
/** Contract address or recipient. Optional for contract deployment transactions. */
|
|
78
|
+
to?: string;
|
|
79
|
+
value: string;
|
|
80
|
+
chainId: number;
|
|
81
|
+
nonce: string;
|
|
82
|
+
gasLimit: string;
|
|
83
|
+
gasPrice?: string;
|
|
84
|
+
maxFeePerGas?: string;
|
|
85
|
+
maxPriorityFeePerGas?: string;
|
|
86
|
+
accessList?: Array<{
|
|
87
|
+
address: string;
|
|
88
|
+
storageKeys: string[];
|
|
89
|
+
}>;
|
|
90
|
+
data?: string;
|
|
91
|
+
}
|
|
92
|
+
interface EvmSignedTx {
|
|
93
|
+
/** Recovery id as `0x`-prefixed hex string. */
|
|
94
|
+
v: string;
|
|
95
|
+
/** ECDSA `r` value as `0x`-prefixed, zero-padded 64-char hex string (32 bytes). */
|
|
96
|
+
r: string;
|
|
97
|
+
/** ECDSA `s` value as `0x`-prefixed, zero-padded 64-char hex string (32 bytes). */
|
|
98
|
+
s: string;
|
|
99
|
+
serializedTx?: string;
|
|
100
|
+
}
|
|
101
|
+
interface EvmSignMsgParams {
|
|
102
|
+
path: string;
|
|
103
|
+
message: string;
|
|
104
|
+
hex?: boolean;
|
|
105
|
+
}
|
|
106
|
+
type EvmSignTypedDataParams = EvmSignTypedDataFull | EvmSignTypedDataHash;
|
|
107
|
+
interface EvmSignTypedDataFull {
|
|
108
|
+
path: string;
|
|
109
|
+
/** Defaults to `'full'` when omitted. */
|
|
110
|
+
mode?: 'full';
|
|
111
|
+
data: {
|
|
112
|
+
domain: EIP712Domain;
|
|
113
|
+
types: Record<string, Array<{
|
|
114
|
+
name: string;
|
|
115
|
+
type: string;
|
|
116
|
+
}>>;
|
|
117
|
+
primaryType: string;
|
|
118
|
+
message: Record<string, unknown>;
|
|
119
|
+
};
|
|
120
|
+
metamaskV4Compat?: boolean;
|
|
121
|
+
}
|
|
122
|
+
interface EvmSignTypedDataHash {
|
|
123
|
+
path: string;
|
|
124
|
+
mode: 'hash';
|
|
125
|
+
domainSeparatorHash: string;
|
|
126
|
+
messageHash: string;
|
|
127
|
+
}
|
|
128
|
+
interface EIP712Domain {
|
|
129
|
+
name?: string;
|
|
130
|
+
version?: string;
|
|
131
|
+
chainId?: number;
|
|
132
|
+
verifyingContract?: string;
|
|
133
|
+
salt?: string;
|
|
134
|
+
[key: string]: unknown;
|
|
135
|
+
}
|
|
136
|
+
interface EvmSignature {
|
|
137
|
+
/** `0x`-prefixed hex string (r + s + v). */
|
|
138
|
+
signature: string;
|
|
139
|
+
address?: string;
|
|
140
|
+
}
|
|
141
|
+
type ProgressCallback = (progress: {
|
|
142
|
+
index: number;
|
|
143
|
+
total: number;
|
|
144
|
+
}) => void;
|
|
145
|
+
interface IEvmMethods {
|
|
146
|
+
evmGetAddress(connectId: string, deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
|
|
147
|
+
evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
|
|
148
|
+
evmGetPublicKey(connectId: string, deviceId: string, params: EvmGetPublicKeyParams): Promise<Response<EvmPublicKey>>;
|
|
149
|
+
evmSignTransaction(connectId: string, deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
|
|
150
|
+
evmSignMessage(connectId: string, deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
|
|
151
|
+
evmSignTypedData(connectId: string, deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
interface BtcGetAddressParams {
|
|
155
|
+
path: string;
|
|
156
|
+
coin?: string;
|
|
157
|
+
showOnDevice?: boolean;
|
|
158
|
+
scriptType?: 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr';
|
|
159
|
+
addressIndex?: number;
|
|
160
|
+
change?: boolean;
|
|
161
|
+
}
|
|
162
|
+
interface BtcAddress {
|
|
163
|
+
address: string;
|
|
164
|
+
path: string;
|
|
165
|
+
}
|
|
166
|
+
interface BtcGetPublicKeyParams {
|
|
167
|
+
path: string;
|
|
168
|
+
coin?: string;
|
|
169
|
+
showOnDevice?: boolean;
|
|
170
|
+
}
|
|
171
|
+
interface BtcPublicKey {
|
|
172
|
+
xpub: string;
|
|
173
|
+
publicKey: string;
|
|
174
|
+
/** Parent key fingerprint (BIP-32), not the master fingerprint. */
|
|
175
|
+
fingerprint: number;
|
|
176
|
+
chainCode: string;
|
|
177
|
+
path: string;
|
|
178
|
+
depth: number;
|
|
179
|
+
}
|
|
180
|
+
interface BtcSignTxParams {
|
|
181
|
+
psbt?: string;
|
|
182
|
+
inputs?: BtcTxInput[];
|
|
183
|
+
outputs?: BtcTxOutput[];
|
|
184
|
+
refTxs?: BtcRefTransaction[];
|
|
185
|
+
coin: string;
|
|
186
|
+
locktime?: number;
|
|
187
|
+
version?: number;
|
|
188
|
+
}
|
|
189
|
+
interface BtcTxInput {
|
|
190
|
+
path: string;
|
|
191
|
+
prevHash: string;
|
|
192
|
+
prevIndex: number;
|
|
193
|
+
amount: string;
|
|
194
|
+
scriptType?: 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr';
|
|
195
|
+
sequence?: number;
|
|
196
|
+
}
|
|
197
|
+
interface BtcTxOutput {
|
|
198
|
+
address?: string;
|
|
199
|
+
path?: string;
|
|
200
|
+
amount: string;
|
|
201
|
+
scriptType?: 'p2pkh' | 'p2sh' | 'p2wpkh' | 'p2wsh' | 'p2tr';
|
|
202
|
+
}
|
|
203
|
+
interface BtcRefTransaction {
|
|
204
|
+
hash: string;
|
|
205
|
+
version: number;
|
|
206
|
+
inputs: Array<{
|
|
207
|
+
prevHash: string;
|
|
208
|
+
prevIndex: number;
|
|
209
|
+
script: string;
|
|
210
|
+
sequence: number;
|
|
211
|
+
}>;
|
|
212
|
+
outputs: Array<{
|
|
213
|
+
amount: string;
|
|
214
|
+
scriptPubKey: string;
|
|
215
|
+
}>;
|
|
216
|
+
locktime: number;
|
|
217
|
+
}
|
|
218
|
+
interface BtcSignedTx {
|
|
219
|
+
signatures: string[];
|
|
220
|
+
serializedTx: string;
|
|
221
|
+
txid?: string;
|
|
222
|
+
signedPsbt?: string;
|
|
223
|
+
}
|
|
224
|
+
interface BtcSignMsgParams {
|
|
225
|
+
path: string;
|
|
226
|
+
message: string;
|
|
227
|
+
coin?: string;
|
|
228
|
+
}
|
|
229
|
+
interface BtcSignature {
|
|
230
|
+
signature: string;
|
|
231
|
+
address: string;
|
|
232
|
+
}
|
|
233
|
+
interface IBtcMethods {
|
|
234
|
+
btcGetAddress(connectId: string, deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
|
|
235
|
+
btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
|
|
236
|
+
btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
|
|
237
|
+
btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
|
|
238
|
+
btcSignMessage(connectId: string, deviceId: string, params: BtcSignMsgParams): Promise<Response<BtcSignature>>;
|
|
239
|
+
btcGetMasterFingerprint(connectId: string, deviceId: string): Promise<Response<{
|
|
240
|
+
masterFingerprint: string;
|
|
241
|
+
}>>;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
interface SolGetAddressParams {
|
|
245
|
+
path: string;
|
|
246
|
+
showOnDevice?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface SolAddress {
|
|
249
|
+
/** Base58-encoded Solana address */
|
|
250
|
+
address: string;
|
|
251
|
+
path: string;
|
|
252
|
+
}
|
|
253
|
+
interface SolGetPublicKeyParams {
|
|
254
|
+
path: string;
|
|
255
|
+
showOnDevice?: boolean;
|
|
256
|
+
}
|
|
257
|
+
interface SolPublicKey {
|
|
258
|
+
/** Base58-encoded Ed25519 public key (same as the Solana address) */
|
|
259
|
+
publicKey: string;
|
|
260
|
+
path: string;
|
|
261
|
+
}
|
|
262
|
+
interface SolSignTxParams {
|
|
263
|
+
path: string;
|
|
264
|
+
/** Hex-encoded serialized transaction bytes (no 0x prefix) */
|
|
265
|
+
serializedTx: string;
|
|
266
|
+
additionalInfo?: {
|
|
267
|
+
tokenAccountsInfos?: Array<{
|
|
268
|
+
baseAddress: string;
|
|
269
|
+
tokenProgram: string;
|
|
270
|
+
tokenMint: string;
|
|
271
|
+
tokenAccount: string;
|
|
272
|
+
}>;
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
interface SolSignedTx {
|
|
276
|
+
/** Hex-encoded Ed25519 signature (no 0x prefix) */
|
|
277
|
+
signature: string;
|
|
278
|
+
}
|
|
279
|
+
interface SolSignMsgParams {
|
|
280
|
+
path: string;
|
|
281
|
+
/** Message bytes as hex string (no 0x prefix) */
|
|
282
|
+
message: string;
|
|
283
|
+
}
|
|
284
|
+
interface SolSignature {
|
|
285
|
+
/** Hex-encoded Ed25519 signature (no 0x prefix) */
|
|
286
|
+
signature: string;
|
|
287
|
+
}
|
|
288
|
+
interface ISolMethods {
|
|
289
|
+
solGetAddress(connectId: string, deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
|
|
290
|
+
solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
|
|
291
|
+
solGetPublicKey(connectId: string, deviceId: string, params: SolGetPublicKeyParams): Promise<Response<SolPublicKey>>;
|
|
292
|
+
solSignTransaction(connectId: string, deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
|
|
293
|
+
solSignMessage(connectId: string, deviceId: string, params: SolSignMsgParams): Promise<Response<SolSignature>>;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
interface QrDisplayData {
|
|
297
|
+
urType: string;
|
|
298
|
+
urData: string;
|
|
299
|
+
animated: boolean;
|
|
300
|
+
}
|
|
301
|
+
interface QrResponseData {
|
|
302
|
+
urType: string;
|
|
303
|
+
urData: string;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
declare const DEVICE_EVENT = "DEVICE_EVENT";
|
|
307
|
+
/** Events originating from the hardware device. */
|
|
308
|
+
declare const DEVICE: {
|
|
309
|
+
readonly CONNECT: "device-connect";
|
|
310
|
+
readonly DISCONNECT: "device-disconnect";
|
|
311
|
+
readonly CHANGED: "device-changed";
|
|
312
|
+
readonly ACQUIRE: "device-acquire";
|
|
313
|
+
readonly RELEASE: "device-release";
|
|
314
|
+
readonly FEATURES: "features";
|
|
315
|
+
readonly SUPPORT_FEATURES: "support_features";
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
declare const UI_EVENT = "UI_EVENT";
|
|
319
|
+
declare const UI_REQUEST: {
|
|
320
|
+
readonly REQUEST_PIN: "ui-request-pin";
|
|
321
|
+
readonly REQUEST_PASSPHRASE: "ui-request-passphrase";
|
|
322
|
+
readonly REQUEST_PASSPHRASE_ON_DEVICE: "ui-request-passphrase-on-device";
|
|
323
|
+
readonly REQUEST_BUTTON: "ui-request-button";
|
|
324
|
+
readonly REQUEST_QR_DISPLAY: "ui-request-qr-display";
|
|
325
|
+
readonly REQUEST_QR_SCAN: "ui-request-qr-scan";
|
|
326
|
+
readonly REQUEST_DEVICE_PERMISSION: "ui-request-device-permission";
|
|
327
|
+
readonly REQUEST_SELECT_DEVICE: "ui-request-select-device";
|
|
328
|
+
readonly CLOSE_UI_WINDOW: "ui-close";
|
|
329
|
+
readonly DEVICE_PROGRESS: "ui-device_progress";
|
|
330
|
+
readonly FIRMWARE_PROGRESS: "ui-firmware-progress";
|
|
331
|
+
readonly FIRMWARE_TIP: "ui-firmware-tip";
|
|
332
|
+
};
|
|
333
|
+
declare const UI_RESPONSE: {
|
|
334
|
+
readonly RECEIVE_PIN: "receive-pin";
|
|
335
|
+
readonly RECEIVE_PASSPHRASE: "receive-passphrase";
|
|
336
|
+
readonly RECEIVE_PASSPHRASE_ON_DEVICE: "receive-passphrase-on-device";
|
|
337
|
+
readonly RECEIVE_QR_RESPONSE: "receive-qr-response";
|
|
338
|
+
readonly RECEIVE_SELECT_DEVICE: "receive-select-device";
|
|
339
|
+
readonly CANCEL: "cancel";
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/** Events generated by SDK internal detection (not from hardware directly). */
|
|
343
|
+
declare const SDK: {
|
|
344
|
+
readonly DEVICE_STUCK: "device-stuck";
|
|
345
|
+
readonly DEVICE_UNRESPONSIVE: "device-unresponsive";
|
|
346
|
+
readonly DEVICE_RECOVERED: "device-recovered";
|
|
347
|
+
readonly DEVICE_INTERACTION: "device-interaction";
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
type ChainCapability = 'evm' | 'btc' | 'sol';
|
|
351
|
+
interface PassphraseResponse {
|
|
352
|
+
passphrase: string;
|
|
353
|
+
/** If true, passphrase will be entered on the device. `passphrase` field is ignored. */
|
|
354
|
+
onDevice?: boolean;
|
|
355
|
+
}
|
|
356
|
+
type DeviceEvent = {
|
|
357
|
+
type: typeof DEVICE.CONNECT;
|
|
358
|
+
payload: DeviceInfo;
|
|
359
|
+
} | {
|
|
360
|
+
type: typeof DEVICE.DISCONNECT;
|
|
361
|
+
payload: {
|
|
362
|
+
connectId: string;
|
|
363
|
+
};
|
|
364
|
+
} | {
|
|
365
|
+
type: typeof DEVICE.CHANGED;
|
|
366
|
+
payload: DeviceInfo;
|
|
367
|
+
};
|
|
368
|
+
type UiRequestEvent = {
|
|
369
|
+
type: typeof UI_REQUEST.REQUEST_PIN;
|
|
370
|
+
payload: {
|
|
371
|
+
device: DeviceInfo;
|
|
372
|
+
};
|
|
373
|
+
} | {
|
|
374
|
+
type: typeof UI_REQUEST.REQUEST_PASSPHRASE;
|
|
375
|
+
payload: {
|
|
376
|
+
device: DeviceInfo;
|
|
377
|
+
};
|
|
378
|
+
} | {
|
|
379
|
+
type: typeof UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE;
|
|
380
|
+
payload: {
|
|
381
|
+
device: DeviceInfo;
|
|
382
|
+
};
|
|
383
|
+
} | {
|
|
384
|
+
type: typeof UI_REQUEST.REQUEST_BUTTON;
|
|
385
|
+
payload: {
|
|
386
|
+
device: DeviceInfo;
|
|
387
|
+
code?: string;
|
|
388
|
+
};
|
|
389
|
+
} | {
|
|
390
|
+
type: typeof UI_REQUEST.REQUEST_QR_DISPLAY;
|
|
391
|
+
payload: {
|
|
392
|
+
device: DeviceInfo;
|
|
393
|
+
data: QrDisplayData;
|
|
394
|
+
};
|
|
395
|
+
} | {
|
|
396
|
+
type: typeof UI_REQUEST.REQUEST_QR_SCAN;
|
|
397
|
+
payload: {
|
|
398
|
+
device: DeviceInfo;
|
|
399
|
+
};
|
|
400
|
+
} | {
|
|
401
|
+
type: typeof UI_REQUEST.REQUEST_DEVICE_PERMISSION;
|
|
402
|
+
payload: Record<string, never>;
|
|
403
|
+
} | {
|
|
404
|
+
type: typeof UI_REQUEST.REQUEST_SELECT_DEVICE;
|
|
405
|
+
payload: {
|
|
406
|
+
devices: DeviceInfo[];
|
|
407
|
+
};
|
|
408
|
+
} | {
|
|
409
|
+
type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
|
|
410
|
+
payload: Record<string, never>;
|
|
411
|
+
};
|
|
412
|
+
type SdkEvent = {
|
|
413
|
+
type: typeof SDK.DEVICE_INTERACTION;
|
|
414
|
+
payload: {
|
|
415
|
+
connectId: string;
|
|
416
|
+
action: string;
|
|
417
|
+
};
|
|
418
|
+
} | {
|
|
419
|
+
type: typeof SDK.DEVICE_STUCK;
|
|
420
|
+
payload: {
|
|
421
|
+
connectId: string;
|
|
422
|
+
};
|
|
423
|
+
} | {
|
|
424
|
+
type: typeof SDK.DEVICE_UNRESPONSIVE;
|
|
425
|
+
payload: {
|
|
426
|
+
connectId: string;
|
|
427
|
+
};
|
|
428
|
+
} | {
|
|
429
|
+
type: typeof SDK.DEVICE_RECOVERED;
|
|
430
|
+
payload: {
|
|
431
|
+
connectId: string;
|
|
432
|
+
};
|
|
433
|
+
};
|
|
434
|
+
type HardwareEvent = DeviceEvent | UiRequestEvent | SdkEvent;
|
|
435
|
+
type DeviceEventListener = (event: HardwareEvent) => void;
|
|
436
|
+
/**
|
|
437
|
+
* Type-safe event map for IHardwareWallet.on / .off.
|
|
438
|
+
*
|
|
439
|
+
* Each key is a concrete event string (e.g. DEVICE.CONNECT = 'device-connect'),
|
|
440
|
+
* and the value is the narrowed event object the listener will receive.
|
|
441
|
+
*/
|
|
442
|
+
interface HardwareEventMap {
|
|
443
|
+
[DEVICE.CONNECT]: {
|
|
444
|
+
type: typeof DEVICE.CONNECT;
|
|
445
|
+
payload: DeviceInfo;
|
|
446
|
+
};
|
|
447
|
+
[DEVICE.DISCONNECT]: {
|
|
448
|
+
type: typeof DEVICE.DISCONNECT;
|
|
449
|
+
payload: {
|
|
450
|
+
connectId: string;
|
|
451
|
+
};
|
|
452
|
+
};
|
|
453
|
+
[DEVICE.CHANGED]: {
|
|
454
|
+
type: typeof DEVICE.CHANGED;
|
|
455
|
+
payload: DeviceInfo;
|
|
456
|
+
};
|
|
457
|
+
[UI_REQUEST.REQUEST_PIN]: {
|
|
458
|
+
type: typeof UI_REQUEST.REQUEST_PIN;
|
|
459
|
+
payload: {
|
|
460
|
+
device: DeviceInfo;
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
[UI_REQUEST.REQUEST_PASSPHRASE]: {
|
|
464
|
+
type: typeof UI_REQUEST.REQUEST_PASSPHRASE;
|
|
465
|
+
payload: {
|
|
466
|
+
device: DeviceInfo;
|
|
467
|
+
};
|
|
468
|
+
};
|
|
469
|
+
[UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE]: {
|
|
470
|
+
type: typeof UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE;
|
|
471
|
+
payload: {
|
|
472
|
+
device: DeviceInfo;
|
|
473
|
+
};
|
|
474
|
+
};
|
|
475
|
+
[UI_REQUEST.REQUEST_BUTTON]: {
|
|
476
|
+
type: typeof UI_REQUEST.REQUEST_BUTTON;
|
|
477
|
+
payload: {
|
|
478
|
+
device: DeviceInfo;
|
|
479
|
+
code?: string;
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
[UI_REQUEST.REQUEST_QR_DISPLAY]: {
|
|
483
|
+
type: typeof UI_REQUEST.REQUEST_QR_DISPLAY;
|
|
484
|
+
payload: {
|
|
485
|
+
device: DeviceInfo;
|
|
486
|
+
data: QrDisplayData;
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
[UI_REQUEST.REQUEST_QR_SCAN]: {
|
|
490
|
+
type: typeof UI_REQUEST.REQUEST_QR_SCAN;
|
|
491
|
+
payload: {
|
|
492
|
+
device: DeviceInfo;
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
[UI_REQUEST.REQUEST_DEVICE_PERMISSION]: {
|
|
496
|
+
type: typeof UI_REQUEST.REQUEST_DEVICE_PERMISSION;
|
|
497
|
+
payload: Record<string, never>;
|
|
498
|
+
};
|
|
499
|
+
[UI_REQUEST.REQUEST_SELECT_DEVICE]: {
|
|
500
|
+
type: typeof UI_REQUEST.REQUEST_SELECT_DEVICE;
|
|
501
|
+
payload: {
|
|
502
|
+
devices: DeviceInfo[];
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
[UI_REQUEST.CLOSE_UI_WINDOW]: {
|
|
506
|
+
type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
|
|
507
|
+
payload: Record<string, never>;
|
|
508
|
+
};
|
|
509
|
+
[SDK.DEVICE_INTERACTION]: {
|
|
510
|
+
type: typeof SDK.DEVICE_INTERACTION;
|
|
511
|
+
payload: {
|
|
512
|
+
connectId: string;
|
|
513
|
+
action: string;
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
[SDK.DEVICE_STUCK]: {
|
|
517
|
+
type: typeof SDK.DEVICE_STUCK;
|
|
518
|
+
payload: {
|
|
519
|
+
connectId: string;
|
|
520
|
+
};
|
|
521
|
+
};
|
|
522
|
+
[SDK.DEVICE_UNRESPONSIVE]: {
|
|
523
|
+
type: typeof SDK.DEVICE_UNRESPONSIVE;
|
|
524
|
+
payload: {
|
|
525
|
+
connectId: string;
|
|
526
|
+
};
|
|
527
|
+
};
|
|
528
|
+
[SDK.DEVICE_RECOVERED]: {
|
|
529
|
+
type: typeof SDK.DEVICE_RECOVERED;
|
|
530
|
+
payload: {
|
|
531
|
+
connectId: string;
|
|
532
|
+
};
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* UI handler for interactive request-response flows.
|
|
537
|
+
* Adapters call these when they need user input (PIN, passphrase, QR scan).
|
|
538
|
+
* Pure notifications (button confirm, progress) go through events instead.
|
|
539
|
+
*/
|
|
540
|
+
interface IUiHandler {
|
|
541
|
+
onPinRequest(device: DeviceInfo): Promise<string>;
|
|
542
|
+
onPassphraseRequest(device: DeviceInfo): Promise<string | PassphraseResponse>;
|
|
543
|
+
onQrDisplay(device: DeviceInfo, data: QrDisplayData): Promise<QrResponseData>;
|
|
544
|
+
onSelectDevice(devices: DeviceInfo[]): Promise<string>;
|
|
545
|
+
/**
|
|
546
|
+
* Check if device access permission is already granted.
|
|
547
|
+
* Returns { granted, context? }.
|
|
548
|
+
* - granted: true → skip onDevicePermission
|
|
549
|
+
* - granted: false → adapter calls onDevicePermission with the context
|
|
550
|
+
* - context: consumer-defined data passed through to onDevicePermission
|
|
551
|
+
*
|
|
552
|
+
* When connectId/deviceId are undefined (searchDevices), check environment-level
|
|
553
|
+
* permissions (USB: any paired device exists; BLE: bluetooth on + location permission).
|
|
554
|
+
* When connectId/deviceId are provided (business methods), check device-level
|
|
555
|
+
* permissions (USB: target device authorized; BLE: bluetooth on + device connected).
|
|
556
|
+
*/
|
|
557
|
+
checkDevicePermission?(params: {
|
|
558
|
+
transportType: TransportType;
|
|
559
|
+
connectId?: string;
|
|
560
|
+
deviceId?: string;
|
|
561
|
+
}): Promise<{
|
|
562
|
+
granted: boolean;
|
|
563
|
+
context?: Record<string, unknown>;
|
|
564
|
+
}>;
|
|
565
|
+
/**
|
|
566
|
+
* Request device access permission from the user.
|
|
567
|
+
* Only called when checkDevicePermission returns granted: false (or is not set).
|
|
568
|
+
*
|
|
569
|
+
* The handler decides what to do based on transportType + context:
|
|
570
|
+
* - usb/hid: open pairing page or call requestWebUSBDevice
|
|
571
|
+
* - ble: enable bluetooth, request location permission, start scanning
|
|
572
|
+
*/
|
|
573
|
+
onDevicePermission(params: {
|
|
574
|
+
transportType: TransportType;
|
|
575
|
+
context?: Record<string, unknown>;
|
|
576
|
+
}): Promise<void>;
|
|
577
|
+
}
|
|
578
|
+
interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, ISolMethods {
|
|
579
|
+
readonly vendor: string;
|
|
580
|
+
readonly activeTransport: TransportType | null;
|
|
581
|
+
init(config: TConfig): Promise<void>;
|
|
582
|
+
dispose(): Promise<void>;
|
|
583
|
+
getAvailableTransports(): TransportType[];
|
|
584
|
+
switchTransport(type: TransportType): Promise<void>;
|
|
585
|
+
searchDevices(): Promise<DeviceInfo[]>;
|
|
586
|
+
connectDevice(connectId: string): Promise<Response<string>>;
|
|
587
|
+
disconnectDevice(connectId: string): Promise<void>;
|
|
588
|
+
getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
|
|
589
|
+
getSupportedChains(): ChainCapability[];
|
|
590
|
+
cancel(connectId: string): void;
|
|
591
|
+
setUiHandler(handler: Partial<IUiHandler>): void;
|
|
592
|
+
on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
593
|
+
on(event: string, listener: DeviceEventListener): void;
|
|
594
|
+
off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
595
|
+
off(event: string, listener: DeviceEventListener): void;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Low-level device descriptor from Transport layer.
|
|
600
|
+
* Represents a physical device detected by USB/BLE scanning.
|
|
601
|
+
*/
|
|
602
|
+
interface DeviceDescriptor {
|
|
603
|
+
/** Unique device path (USB serial number, BLE address, etc.) */
|
|
604
|
+
path: string;
|
|
605
|
+
/** USB product ID */
|
|
606
|
+
product?: number;
|
|
607
|
+
/** USB vendor ID */
|
|
608
|
+
vendor?: number;
|
|
609
|
+
/** Device type/model identifier */
|
|
610
|
+
type?: string;
|
|
611
|
+
}
|
|
612
|
+
interface DeviceConnectEvent {
|
|
613
|
+
type: 'device-connected';
|
|
614
|
+
descriptor: DeviceDescriptor;
|
|
615
|
+
}
|
|
616
|
+
interface DeviceDisconnectEvent {
|
|
617
|
+
type: 'device-disconnected';
|
|
618
|
+
descriptor: DeviceDescriptor;
|
|
619
|
+
}
|
|
620
|
+
type DeviceChangeEvent = DeviceConnectEvent | DeviceDisconnectEvent;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Per-device serial job queue with preemption support and stuck recovery.
|
|
624
|
+
* Ensures that only one operation runs at a time per device, with intelligent
|
|
625
|
+
* handling of conflicting operations.
|
|
626
|
+
*/
|
|
627
|
+
type Interruptibility = 'none' | 'safe' | 'confirm';
|
|
628
|
+
type PreemptionDecision = 'cancel-current' | 'wait' | 'reject-new';
|
|
629
|
+
interface JobOptions {
|
|
630
|
+
interruptibility?: Interruptibility;
|
|
631
|
+
label?: string;
|
|
632
|
+
}
|
|
633
|
+
interface ActiveJobInfo {
|
|
634
|
+
label?: string;
|
|
635
|
+
interruptibility: Interruptibility;
|
|
636
|
+
startedAt: number;
|
|
637
|
+
}
|
|
638
|
+
interface PreemptionEvent {
|
|
639
|
+
deviceId: string;
|
|
640
|
+
currentJob: ActiveJobInfo;
|
|
641
|
+
newJob: {
|
|
642
|
+
label?: string;
|
|
643
|
+
interruptibility: Interruptibility;
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
declare class DeviceJobQueue {
|
|
647
|
+
private readonly _queues;
|
|
648
|
+
private readonly _active;
|
|
649
|
+
/**
|
|
650
|
+
* Called when a new job conflicts with an active 'confirm'-level job.
|
|
651
|
+
* UI should show a dialog and return the user's decision.
|
|
652
|
+
* If not set, defaults to 'wait' (queue behind current job).
|
|
653
|
+
*/
|
|
654
|
+
onPreemptionRequest?: (event: PreemptionEvent) => Promise<PreemptionDecision>;
|
|
655
|
+
/**
|
|
656
|
+
* Enqueue a job for a specific device.
|
|
657
|
+
* If a job is already running for this device, behavior depends on interruptibility:
|
|
658
|
+
* - 'none': new job queues silently (no preemption possible)
|
|
659
|
+
* - 'safe': current job is auto-cancelled, new job runs immediately after
|
|
660
|
+
* - 'confirm': onPreemptionRequest is called to ask user
|
|
661
|
+
*/
|
|
662
|
+
enqueue<T>(deviceId: string, job: (signal: AbortSignal) => Promise<T>, options?: JobOptions): Promise<T>;
|
|
663
|
+
/** Manually cancel the active job on a device. Returns false if job is non-interruptible. */
|
|
664
|
+
cancelActive(deviceId: string): boolean;
|
|
665
|
+
/** Force cancel regardless of interruptibility. Use for device stuck recovery. */
|
|
666
|
+
forceCancelActive(deviceId: string): boolean;
|
|
667
|
+
/** Get info about the currently active job for a device, or null if idle. */
|
|
668
|
+
getActiveJob(deviceId: string): ActiveJobInfo | null;
|
|
669
|
+
clear(): void;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Abstraction for UI communication during device interactions.
|
|
674
|
+
* Implementations handle different execution contexts:
|
|
675
|
+
* - DirectUiBridge: same-process event emitter (default)
|
|
676
|
+
* - IframeUiBridge: postMessage-based (future)
|
|
677
|
+
* - ExtensionUiBridge: chrome.runtime.sendMessage (future)
|
|
678
|
+
*/
|
|
679
|
+
interface IUiBridge {
|
|
680
|
+
/** Ask the user for PIN entry. Returns the PIN string. */
|
|
681
|
+
requestPin(device: DeviceInfo, signal?: AbortSignal): Promise<string>;
|
|
682
|
+
/** Ask the user for passphrase entry. Returns the passphrase string. */
|
|
683
|
+
requestPassphrase(device: DeviceInfo, signal?: AbortSignal): Promise<string>;
|
|
684
|
+
/** Notify the UI about a button press request on the device. */
|
|
685
|
+
notifyButton(device: DeviceInfo, code?: string): void;
|
|
686
|
+
/**
|
|
687
|
+
* Ask the user whether to preempt the current device operation.
|
|
688
|
+
* Only called for 'confirm'-level operations.
|
|
689
|
+
*/
|
|
690
|
+
requestPreemption(device: DeviceInfo, activeLabel: string, newLabel: string): Promise<PreemptionDecision>;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Minimal device info returned during discovery (searchDevices).
|
|
695
|
+
* At scan time, full DeviceInfo fields like firmwareVersion are not yet available.
|
|
696
|
+
*/
|
|
697
|
+
interface ConnectorDevice {
|
|
698
|
+
connectId: string;
|
|
699
|
+
deviceId: string;
|
|
700
|
+
name: string;
|
|
701
|
+
model?: string;
|
|
702
|
+
}
|
|
703
|
+
interface ConnectorSession {
|
|
704
|
+
sessionId: string;
|
|
705
|
+
deviceInfo: DeviceInfo;
|
|
706
|
+
}
|
|
707
|
+
type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';
|
|
708
|
+
interface ConnectorEventMap {
|
|
709
|
+
'device-connect': {
|
|
710
|
+
device: ConnectorDevice;
|
|
711
|
+
};
|
|
712
|
+
'device-disconnect': {
|
|
713
|
+
connectId: string;
|
|
714
|
+
};
|
|
715
|
+
'ui-request': {
|
|
716
|
+
type: string;
|
|
717
|
+
payload?: unknown;
|
|
718
|
+
};
|
|
719
|
+
'ui-event': {
|
|
720
|
+
type: string;
|
|
721
|
+
payload?: unknown;
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
interface IConnector {
|
|
725
|
+
searchDevices(): Promise<ConnectorDevice[]>;
|
|
726
|
+
connect(deviceId?: string): Promise<ConnectorSession>;
|
|
727
|
+
disconnect(sessionId: string): Promise<void>;
|
|
728
|
+
call(sessionId: string, method: string, params: unknown): Promise<unknown>;
|
|
729
|
+
cancel(sessionId: string): Promise<void>;
|
|
730
|
+
/** Send a UI response (e.g. PIN, passphrase) to the device. */
|
|
731
|
+
uiResponse(response: {
|
|
732
|
+
type: string;
|
|
733
|
+
payload: unknown;
|
|
734
|
+
}): void;
|
|
735
|
+
on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
|
|
736
|
+
off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
|
|
737
|
+
reset(): void;
|
|
738
|
+
}
|
|
739
|
+
interface IDesktopHardwareBridge {
|
|
740
|
+
searchDevices(params: {
|
|
741
|
+
vendor: VendorType;
|
|
742
|
+
}): Promise<ConnectorDevice[]>;
|
|
743
|
+
connect(params: {
|
|
744
|
+
vendor: VendorType;
|
|
745
|
+
deviceId?: string;
|
|
746
|
+
}): Promise<ConnectorSession>;
|
|
747
|
+
disconnect(params: {
|
|
748
|
+
vendor: VendorType;
|
|
749
|
+
sessionId: string;
|
|
750
|
+
}): Promise<void>;
|
|
751
|
+
call(params: {
|
|
752
|
+
vendor: VendorType;
|
|
753
|
+
sessionId: string;
|
|
754
|
+
method: string;
|
|
755
|
+
callParams: unknown;
|
|
756
|
+
}): Promise<unknown>;
|
|
757
|
+
cancel(params: {
|
|
758
|
+
vendor: VendorType;
|
|
759
|
+
sessionId: string;
|
|
760
|
+
}): Promise<void>;
|
|
761
|
+
uiResponse(params: {
|
|
762
|
+
vendor: VendorType;
|
|
763
|
+
response: {
|
|
764
|
+
type: string;
|
|
765
|
+
payload: unknown;
|
|
766
|
+
};
|
|
767
|
+
}): void;
|
|
768
|
+
reset(params: {
|
|
769
|
+
vendor: VendorType;
|
|
770
|
+
}): void;
|
|
771
|
+
/** Register an event handler for connector events forwarded from the main process. */
|
|
772
|
+
onEvent(params: {
|
|
773
|
+
vendor: VendorType;
|
|
774
|
+
}, handler: (event: {
|
|
775
|
+
type: ConnectorEventType;
|
|
776
|
+
data: unknown;
|
|
777
|
+
}) => void): void;
|
|
778
|
+
/** Unregister a previously registered event handler. */
|
|
779
|
+
offEvent(params: {
|
|
780
|
+
vendor: VendorType;
|
|
781
|
+
}, handler: (event: {
|
|
782
|
+
type: ConnectorEventType;
|
|
783
|
+
data: unknown;
|
|
784
|
+
}) => void): void;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Create an IConnector from a desktop IPC bridge + vendor name.
|
|
788
|
+
* Events are forwarded via bridge.onEvent/offEvent.
|
|
789
|
+
*/
|
|
790
|
+
declare function createDesktopBridgeConnector(vendor: VendorType, bridge: IDesktopHardwareBridge): IConnector;
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Minimal typed event emitter using Map<string, Set<listener>>.
|
|
794
|
+
* Each adapter uses this for device events (connect, disconnect, pin, etc.).
|
|
795
|
+
*
|
|
796
|
+
* TMap is a record mapping event name strings to their payload types.
|
|
797
|
+
* Example:
|
|
798
|
+
* type MyEvents = { 'connect': { id: string }; 'disconnect': { id: string } };
|
|
799
|
+
* const emitter = new TypedEventEmitter<MyEvents>();
|
|
800
|
+
* emitter.on('connect', (data) => { data.id }); // data is { id: string }
|
|
801
|
+
*
|
|
802
|
+
* For backward compatibility, TMap defaults to Record<string, any> so that
|
|
803
|
+
* existing code using `new TypedEventEmitter<SomeUnionType>()` still compiles.
|
|
804
|
+
*/
|
|
805
|
+
declare class TypedEventEmitter<TMap extends Record<string, any> = Record<string, any>> {
|
|
806
|
+
private readonly _listeners;
|
|
807
|
+
on<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;
|
|
808
|
+
on(event: string, listener: (event: any) => void): void;
|
|
809
|
+
off<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;
|
|
810
|
+
off(event: string, listener: (event: any) => void): void;
|
|
811
|
+
emit<K extends keyof TMap & string>(event: K, data: TMap[K]): void;
|
|
812
|
+
emit(event: string, data: unknown): void;
|
|
813
|
+
removeAllListeners(): void;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Compare two semver strings (e.g. "2.1.0" vs "2.3.1").
|
|
818
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
819
|
+
*/
|
|
820
|
+
declare function compareSemver(a: string, b: string): number;
|
|
821
|
+
|
|
822
|
+
export { type ActiveJobInfo, type BtcAddress, type BtcGetAddressParams, type BtcGetPublicKeyParams, type BtcPublicKey, type BtcRefTransaction, type BtcSignMsgParams, type BtcSignTxParams, type BtcSignature, type BtcSignedTx, type BtcTxInput, type BtcTxOutput, type ChainCapability, type ConnectionType, type ConnectorDevice, type ConnectorEventMap, type ConnectorEventType, type ConnectorSession, DEVICE, DEVICE_EVENT, type DeviceChangeEvent, type DeviceConnectEvent, type DeviceDescriptor, type DeviceDisconnectEvent, type DeviceEvent, type DeviceEventListener, type DeviceInfo, DeviceJobQueue, type DeviceTarget, type EIP712Domain, type EvmAddress, type EvmGetAddressParams, type EvmGetPublicKeyParams, type EvmPublicKey, type EvmSignMsgParams, type EvmSignTxParams, type EvmSignTypedDataFull, type EvmSignTypedDataHash, type EvmSignTypedDataParams, type EvmSignature, type EvmSignedTx, type Failure, HardwareErrorCode, type HardwareEvent, type HardwareEventMap, type IBtcMethods, type IConnector, type IDesktopHardwareBridge, type IEvmMethods, type IHardwareWallet, type ISolMethods, type IUiBridge, type IUiHandler, type Interruptibility, type JobOptions, type PassphraseResponse, type PreemptionDecision, type PreemptionEvent, type ProgressCallback, type QrDisplayData, type QrResponseData, type Response, SDK, type SdkEvent, type SolAddress, type SolGetAddressParams, type SolGetPublicKeyParams, type SolPublicKey, type SolSignMsgParams, type SolSignTxParams, type SolSignature, type SolSignedTx, type Success, type TransportType, TypedEventEmitter, UI_EVENT, UI_REQUEST, UI_RESPONSE, type UiRequestEvent, type VendorType, compareSemver, createDesktopBridgeConnector, failure, success };
|