@onekeyfe/hwk-keystone-adapter 1.2.5-alpha.0 → 1.2.5-alpha.2
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 +13 -19
- package/dist/index.d.ts +13 -19
- package/dist/index.js +279 -353
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -158
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -155,9 +155,10 @@ function requireSignatureBytes(hex, expectedBytes, chain) {
|
|
|
155
155
|
}
|
|
156
156
|
return hex;
|
|
157
157
|
}
|
|
158
|
+
var MISSING_MASTER_FINGERPRINT = "00000000";
|
|
158
159
|
function requireBip32MasterFingerprint(value) {
|
|
159
160
|
const fingerprint = parseBip32MasterFingerprint(value);
|
|
160
|
-
if (!fingerprint) {
|
|
161
|
+
if (!fingerprint || fingerprint === MISSING_MASTER_FINGERPRINT) {
|
|
161
162
|
throw new Error("Keystone master fingerprint must be exactly 4 bytes (8 hex characters)");
|
|
162
163
|
}
|
|
163
164
|
return fingerprint;
|
|
@@ -423,7 +424,7 @@ import {
|
|
|
423
424
|
isHwkRecoveryHint,
|
|
424
425
|
isUserRefusal,
|
|
425
426
|
operationMayHaveCompletedParams,
|
|
426
|
-
parseBip32MasterFingerprint as
|
|
427
|
+
parseBip32MasterFingerprint as parseBip32MasterFingerprint3,
|
|
427
428
|
rehydrateConnectorError,
|
|
428
429
|
resolveHardwareOperationTarget as resolveGenericHardwareOperationTarget,
|
|
429
430
|
runAllNetworkGetAddress,
|
|
@@ -431,9 +432,6 @@ import {
|
|
|
431
432
|
success
|
|
432
433
|
} from "@onekeyfe/hwk-adapter-core";
|
|
433
434
|
|
|
434
|
-
// src/adapter/deviceTable.ts
|
|
435
|
-
import { deriveWalletId } from "@onekeyfe/hwk-adapter-core";
|
|
436
|
-
|
|
437
435
|
// src/adapter/pathUtils.ts
|
|
438
436
|
function normalizePath(path) {
|
|
439
437
|
const trimmed = path.trim();
|
|
@@ -478,31 +476,17 @@ var KEYSTONE_BTC_ACCOUNT_FORBIDDEN_MESSAGE = "Keystone BTC is limited to mainnet
|
|
|
478
476
|
|
|
479
477
|
// src/adapter/deviceTable.ts
|
|
480
478
|
var KEYSTONE_WALLET_CONNECT_ID_PREFIX = "keystone-wallet:";
|
|
481
|
-
var
|
|
482
|
-
function walletConnectId(
|
|
483
|
-
return `${KEYSTONE_WALLET_CONNECT_ID_PREFIX}${
|
|
479
|
+
var KEYSTONE_COLD_START_PATH = "m/44'/60'/0'";
|
|
480
|
+
function walletConnectId(masterFingerprint) {
|
|
481
|
+
return `${KEYSTONE_WALLET_CONNECT_ID_PREFIX}${masterFingerprint}`;
|
|
484
482
|
}
|
|
485
483
|
function accountKey(hwkChain, path) {
|
|
486
484
|
return `${hwkChain}:${normalizePath(path)}`;
|
|
487
485
|
}
|
|
488
|
-
function
|
|
489
|
-
const identityAccount = accounts.find(
|
|
490
|
-
(account) => normalizePath(account.path) === KEYSTONE_WALLET_ID_PATH
|
|
491
|
-
);
|
|
492
|
-
if (!identityAccount?.extendedPublicKey) {
|
|
493
|
-
throw new Error(
|
|
494
|
-
`Keystone identity response is missing the extended public key at ${KEYSTONE_WALLET_ID_PATH}`
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
return deriveWalletId(
|
|
498
|
-
`keystone:secp256k1:${KEYSTONE_WALLET_ID_PATH}:${identityAccount.extendedPublicKey.trim()}`
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
|
-
function createDeviceRecord(walletId, masterFingerprint) {
|
|
486
|
+
function createDeviceRecord(masterFingerprint) {
|
|
502
487
|
return {
|
|
503
|
-
walletId,
|
|
504
488
|
masterFingerprint,
|
|
505
|
-
connectId: walletConnectId(
|
|
489
|
+
connectId: walletConnectId(masterFingerprint),
|
|
506
490
|
importedAt: Date.now()
|
|
507
491
|
};
|
|
508
492
|
}
|
|
@@ -517,7 +501,7 @@ function toDeviceInfo(record) {
|
|
|
517
501
|
model: record.model ?? "unknown",
|
|
518
502
|
modelName: record.model,
|
|
519
503
|
firmwareVersion: record.deviceVersion ?? "0.0.0",
|
|
520
|
-
deviceId: record.
|
|
504
|
+
deviceId: record.masterFingerprint,
|
|
521
505
|
connectId: record.connectId,
|
|
522
506
|
connectionType: record.usbSessionId ? "usb" : "qr",
|
|
523
507
|
capabilities: CAPABILITIES,
|
|
@@ -541,22 +525,22 @@ function placeholderDeviceInfo() {
|
|
|
541
525
|
}
|
|
542
526
|
|
|
543
527
|
// src/utils/queueKey.ts
|
|
544
|
-
import { isHardwareOperationId } from "@onekeyfe/hwk-adapter-core";
|
|
528
|
+
import { isHardwareOperationId, parseBip32MasterFingerprint as parseBip32MasterFingerprint2 } from "@onekeyfe/hwk-adapter-core";
|
|
545
529
|
var KEYSTONE_COLD_START_JOB_LABEL = "keystone-cold-start";
|
|
546
530
|
function keystoneQueueKey(connectId, deviceId) {
|
|
547
531
|
return isHardwareOperationId(connectId) ? connectId : deviceId || connectId || KEYSTONE_COLD_START_JOB_LABEL;
|
|
548
532
|
}
|
|
549
|
-
function
|
|
533
|
+
function keystoneMfpFromIdentifier(identifier) {
|
|
550
534
|
const value = identifier.startsWith(KEYSTONE_WALLET_CONNECT_ID_PREFIX) ? identifier.slice(KEYSTONE_WALLET_CONNECT_ID_PREFIX.length) : identifier;
|
|
551
|
-
return
|
|
535
|
+
return parseBip32MasterFingerprint2(value);
|
|
552
536
|
}
|
|
553
537
|
function keystoneCancelQueueKeys(identifiers) {
|
|
554
538
|
const keys = /* @__PURE__ */ new Set();
|
|
555
539
|
for (const identifier of identifiers) {
|
|
556
540
|
if (identifier) {
|
|
557
541
|
keys.add(identifier);
|
|
558
|
-
const
|
|
559
|
-
if (
|
|
542
|
+
const masterFingerprint = keystoneMfpFromIdentifier(identifier);
|
|
543
|
+
if (masterFingerprint) keys.add(masterFingerprint);
|
|
560
544
|
}
|
|
561
545
|
}
|
|
562
546
|
return keys;
|
|
@@ -635,7 +619,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
635
619
|
if (record.qrSynced) {
|
|
636
620
|
this.emitter.emit(DEVICE.CHANGED, { type: DEVICE.CHANGED, payload: info });
|
|
637
621
|
} else {
|
|
638
|
-
this._devices.delete(record.
|
|
622
|
+
this._devices.delete(record.masterFingerprint);
|
|
639
623
|
this.emitter.emit(DEVICE.DISCONNECT, { type: DEVICE.DISCONNECT, payload: info });
|
|
640
624
|
}
|
|
641
625
|
};
|
|
@@ -657,7 +641,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
657
641
|
operationId
|
|
658
642
|
});
|
|
659
643
|
const { book } = prefetched;
|
|
660
|
-
const itemDeviceId = deviceId || prefetched.
|
|
644
|
+
const itemDeviceId = deviceId || prefetched.masterFingerprint || "";
|
|
661
645
|
const scope = this._jobQueue.createCancelScope(
|
|
662
646
|
keystoneQueueKey(effectiveConnectId, itemDeviceId)
|
|
663
647
|
);
|
|
@@ -706,7 +690,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
706
690
|
deviceIdentity: record ? {
|
|
707
691
|
vendor: "keystone",
|
|
708
692
|
type: "walletId",
|
|
709
|
-
value: record.
|
|
693
|
+
value: record.masterFingerprint
|
|
710
694
|
} : void 0
|
|
711
695
|
}
|
|
712
696
|
});
|
|
@@ -851,7 +835,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
851
835
|
const devices = await this.searchDevices(options);
|
|
852
836
|
return devices.map((device) => ({
|
|
853
837
|
searchTargetId: device.connectId,
|
|
854
|
-
// The
|
|
838
|
+
// The master fingerprint is known only after the USB/QR handshake.
|
|
855
839
|
searchTargetReusePolicy: "current-discovery",
|
|
856
840
|
vendor: device.vendor,
|
|
857
841
|
connectionType: device.connectionType,
|
|
@@ -1020,13 +1004,15 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1020
1004
|
getChainFingerprint(connectId, deviceId, chain) {
|
|
1021
1005
|
try {
|
|
1022
1006
|
const target = this._resolveTarget(connectId, deviceId);
|
|
1023
|
-
const
|
|
1024
|
-
if (!
|
|
1007
|
+
const masterFingerprint = target.expectedMasterFingerprint;
|
|
1008
|
+
if (!masterFingerprint) {
|
|
1025
1009
|
return Promise.resolve(
|
|
1026
1010
|
failure(HardwareErrorCode.DeviceNotFound, "Unknown Keystone wallet identity")
|
|
1027
1011
|
);
|
|
1028
1012
|
}
|
|
1029
|
-
return Promise.resolve(
|
|
1013
|
+
return Promise.resolve(
|
|
1014
|
+
success(deriveDeviceFingerprint(`keystone:${chain}:${masterFingerprint}`))
|
|
1015
|
+
);
|
|
1030
1016
|
} catch (err) {
|
|
1031
1017
|
return Promise.resolve(this._errorToFailure(err));
|
|
1032
1018
|
}
|
|
@@ -1056,7 +1042,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1056
1042
|
responseUr = await this._requestQrScanAndAwaitResponse(displayDevice, signal);
|
|
1057
1043
|
} else {
|
|
1058
1044
|
const requestUr = this.urEngine.buildKeyDerivationRequest({
|
|
1059
|
-
schemas: [keySchema("evm",
|
|
1045
|
+
schemas: [keySchema("evm", KEYSTONE_COLD_START_PATH)],
|
|
1060
1046
|
origin: this._origin
|
|
1061
1047
|
});
|
|
1062
1048
|
responseUr = await this._requestQrDisplayAndAwaitResponse(
|
|
@@ -1674,12 +1660,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1674
1660
|
const operation = isHardwareOperationId2(params.operationId) ? this._operations.find(params.operationId) : void 0;
|
|
1675
1661
|
const operationRoute = operation ? this._operationRoutes.get(operation.connectId) : void 0;
|
|
1676
1662
|
const routedToQr = operationRoute?.operationId === operation?.operationId && operationRoute?.connectionType === "qr";
|
|
1677
|
-
if (this._forcedTransport !== "qr" && !routedToQr && !record?.usbSessionId && this._usbConnector && target.
|
|
1678
|
-
record = await this._tryUsbAttach(
|
|
1679
|
-
signal,
|
|
1680
|
-
target.expectedWalletId,
|
|
1681
|
-
record?.masterFingerprint ?? target.expectedMasterFingerprint
|
|
1682
|
-
) ?? record;
|
|
1663
|
+
if (this._forcedTransport !== "qr" && !routedToQr && !record?.usbSessionId && this._usbConnector && target.expectedMasterFingerprint) {
|
|
1664
|
+
record = await this._tryUsbAttach(signal, target.expectedMasterFingerprint) ?? record;
|
|
1683
1665
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1684
1666
|
}
|
|
1685
1667
|
if (this._forcedTransport !== "qr" && !routedToQr && record?.usbSessionId) {
|
|
@@ -1708,7 +1690,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1708
1690
|
}
|
|
1709
1691
|
}
|
|
1710
1692
|
assertAllBooked();
|
|
1711
|
-
return { book,
|
|
1693
|
+
return { book, masterFingerprint: record.masterFingerprint };
|
|
1712
1694
|
}
|
|
1713
1695
|
if (this._forcedTransport === "usb") {
|
|
1714
1696
|
throw createHwkError({
|
|
@@ -1716,12 +1698,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1716
1698
|
message: "USB channel is not connected for this Keystone wallet"
|
|
1717
1699
|
});
|
|
1718
1700
|
}
|
|
1719
|
-
const schemas =
|
|
1720
|
-
{ hwkChain: "evm", path: KEYSTONE_WALLET_ID_PATH },
|
|
1721
|
-
...requestedSchemas.filter(
|
|
1722
|
-
(schema) => normalizePath(schema.path) !== KEYSTONE_WALLET_ID_PATH
|
|
1723
|
-
)
|
|
1724
|
-
];
|
|
1701
|
+
const schemas = requestedSchemas;
|
|
1725
1702
|
const requestUr = this.urEngine.buildKeyDerivationRequest({
|
|
1726
1703
|
schemas: schemas.map((schema) => keySchema(schema.hwkChain, schema.path)),
|
|
1727
1704
|
origin: this._origin
|
|
@@ -1746,78 +1723,54 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1746
1723
|
}
|
|
1747
1724
|
}
|
|
1748
1725
|
assertAllBooked();
|
|
1749
|
-
return { book,
|
|
1726
|
+
return { book, masterFingerprint: record.masterFingerprint };
|
|
1750
1727
|
});
|
|
1751
1728
|
}
|
|
1752
|
-
/**
|
|
1753
|
-
* Resolve only the stable 64-hex wallet identity. The 8-hex BIP32 master
|
|
1754
|
-
* fingerprint is protocol metadata and is never accepted as a lookup key.
|
|
1755
|
-
*/
|
|
1729
|
+
/** Resolve the wallet's master fingerprint from the connectId and/or deviceId the caller passed. */
|
|
1756
1730
|
_resolveTarget(connectId, deviceId) {
|
|
1757
1731
|
const resolvedConnectId = isHardwareOperationId2(connectId) ? this._operations.resolve(connectId).connectId : connectId;
|
|
1758
1732
|
const identifiers = [deviceId, resolvedConnectId].filter(
|
|
1759
1733
|
(identifier) => Boolean(identifier)
|
|
1760
1734
|
);
|
|
1761
1735
|
if (!identifiers.length) return {};
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1736
|
+
const fingerprints = identifiers.map((identifier) => keystoneMfpFromIdentifier(identifier));
|
|
1737
|
+
const expectedMasterFingerprint = fingerprints[0];
|
|
1738
|
+
if (!expectedMasterFingerprint || fingerprints.some((value) => !value)) {
|
|
1764
1739
|
throw createHwkError({
|
|
1765
1740
|
code: HardwareErrorCode.DeviceNotFound,
|
|
1766
|
-
message: "Keystone device lookup requires
|
|
1741
|
+
message: "Keystone device lookup requires the wallet master fingerprint"
|
|
1767
1742
|
});
|
|
1768
1743
|
}
|
|
1769
|
-
|
|
1770
|
-
if (walletIds.some((walletId) => walletId !== expectedWalletId)) {
|
|
1744
|
+
if (fingerprints.some((value) => value !== expectedMasterFingerprint)) {
|
|
1771
1745
|
throw createHwkError({
|
|
1772
1746
|
code: HardwareErrorCode.DeviceMismatch,
|
|
1773
1747
|
message: "Keystone connectId and deviceId identify different wallets"
|
|
1774
1748
|
});
|
|
1775
1749
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
|
-
const record = this._devices.get(expectedWalletId);
|
|
1783
|
-
return record ? {
|
|
1784
|
-
record,
|
|
1785
|
-
expectedWalletId,
|
|
1786
|
-
expectedMasterFingerprint: record.masterFingerprint
|
|
1787
|
-
} : { expectedWalletId };
|
|
1750
|
+
return {
|
|
1751
|
+
record: this._devices.get(expectedMasterFingerprint),
|
|
1752
|
+
expectedMasterFingerprint
|
|
1753
|
+
};
|
|
1788
1754
|
}
|
|
1789
1755
|
_assertParsedIdentity(parsed, expected) {
|
|
1790
|
-
const walletId = deriveKeystoneWalletId(parsed.accounts);
|
|
1791
1756
|
if (expected.expectedMasterFingerprint && parsed.masterFingerprint !== expected.expectedMasterFingerprint) {
|
|
1792
1757
|
throw createHwkError({
|
|
1793
1758
|
code: HardwareErrorCode.DeviceMismatch,
|
|
1794
1759
|
message: `Connected Keystone wallet (mfp ${parsed.masterFingerprint}) does not match the requested wallet fingerprint (${expected.expectedMasterFingerprint})`
|
|
1795
1760
|
});
|
|
1796
1761
|
}
|
|
1797
|
-
if (expected.expectedWalletId && walletId !== expected.expectedWalletId) {
|
|
1798
|
-
throw createHwkError({
|
|
1799
|
-
code: HardwareErrorCode.DeviceMismatch,
|
|
1800
|
-
message: "Connected Keystone wallet does not match the requested wallet identity"
|
|
1801
|
-
});
|
|
1802
|
-
}
|
|
1803
|
-
return walletId;
|
|
1804
1762
|
}
|
|
1805
1763
|
/**
|
|
1806
1764
|
* Folds a parsed account response into the device table. Only non-USB round trips mark
|
|
1807
1765
|
* `qrSynced`, so a USB-only wallet is dropped on disconnect.
|
|
1808
1766
|
*/
|
|
1809
1767
|
_upsertDeviceRecord(parsed, options) {
|
|
1810
|
-
const
|
|
1811
|
-
let record = this._devices.get(
|
|
1768
|
+
const { masterFingerprint } = parsed;
|
|
1769
|
+
let record = this._devices.get(masterFingerprint);
|
|
1812
1770
|
const isNew = !record;
|
|
1813
1771
|
if (!record) {
|
|
1814
|
-
record = createDeviceRecord(
|
|
1815
|
-
this._devices.set(
|
|
1816
|
-
} else if (record.masterFingerprint !== parsed.masterFingerprint) {
|
|
1817
|
-
throw createHwkError({
|
|
1818
|
-
code: HardwareErrorCode.DeviceMismatch,
|
|
1819
|
-
message: "Keystone wallet identity returned an inconsistent master fingerprint"
|
|
1820
|
-
});
|
|
1772
|
+
record = createDeviceRecord(masterFingerprint);
|
|
1773
|
+
this._devices.set(masterFingerprint, record);
|
|
1821
1774
|
}
|
|
1822
1775
|
record.model = parsed.device ?? record.model;
|
|
1823
1776
|
record.deviceVersion = parsed.deviceVersion ?? record.deviceVersion;
|
|
@@ -1830,8 +1783,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1830
1783
|
return record;
|
|
1831
1784
|
}
|
|
1832
1785
|
/**
|
|
1833
|
-
* Opens a permitted USB Keystone
|
|
1834
|
-
*
|
|
1786
|
+
* Opens a permitted USB Keystone and takes its mfp as the wallet identity. A known wallet gains
|
|
1787
|
+
* USB in place (`device-changed`); an unseen one becomes USB-only.
|
|
1835
1788
|
*/
|
|
1836
1789
|
async _connectUsb(expected, searchTargetId, signal) {
|
|
1837
1790
|
if (this._pendingUsbTeardowns > 0 || this._abandonedUsbConnects > 0) {
|
|
@@ -1884,7 +1837,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1884
1837
|
sessionId = session.sessionId;
|
|
1885
1838
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1886
1839
|
const raw = session.deviceInfo.raw;
|
|
1887
|
-
const mfpValue =
|
|
1840
|
+
const mfpValue = parseBip32MasterFingerprint3(raw?.masterFingerprint);
|
|
1888
1841
|
if (!mfpValue) {
|
|
1889
1842
|
throw createHwkError({
|
|
1890
1843
|
code: HardwareErrorCode.DeviceMismatch,
|
|
@@ -1898,26 +1851,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1898
1851
|
message: `Connected Keystone wallet (mfp ${masterFingerprint}) does not match the requested wallet fingerprint (${expected.expectedMasterFingerprint})`
|
|
1899
1852
|
});
|
|
1900
1853
|
}
|
|
1901
|
-
const
|
|
1902
|
-
schemas: [keySchema("evm", KEYSTONE_WALLET_ID_PATH)],
|
|
1903
|
-
origin: this._origin
|
|
1904
|
-
});
|
|
1905
|
-
const identityResult = await this._callUsbConnector(
|
|
1906
|
-
session.sessionId,
|
|
1907
|
-
"resolveUr",
|
|
1908
|
-
identityRequest
|
|
1909
|
-
);
|
|
1910
|
-
_KeystoneAdapter._throwIfAborted(signal);
|
|
1911
|
-
if (!identityResult.success) {
|
|
1912
|
-
throw rehydrateConnectorError(identityResult.error);
|
|
1913
|
-
}
|
|
1914
|
-
const parsed = this.urEngine.parseAccountResponse(identityResult.payload);
|
|
1915
|
-
this._assertParsedIdentity(parsed, {
|
|
1916
|
-
...expected,
|
|
1917
|
-
expectedMasterFingerprint: expected.expectedMasterFingerprint ?? masterFingerprint
|
|
1918
|
-
});
|
|
1919
|
-
const walletId = deriveKeystoneWalletId(parsed.accounts);
|
|
1920
|
-
const previousUsbSessionId = this._devices.get(walletId)?.usbSessionId;
|
|
1854
|
+
const previousUsbSessionId = this._devices.get(masterFingerprint)?.usbSessionId;
|
|
1921
1855
|
if (previousUsbSessionId && previousUsbSessionId !== session.sessionId) {
|
|
1922
1856
|
try {
|
|
1923
1857
|
await this._usbConnector.disconnect(previousUsbSessionId);
|
|
@@ -1925,10 +1859,13 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1925
1859
|
}
|
|
1926
1860
|
}
|
|
1927
1861
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1928
|
-
const record = this._upsertDeviceRecord(
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1862
|
+
const record = this._upsertDeviceRecord(
|
|
1863
|
+
{ masterFingerprint, accounts: [] },
|
|
1864
|
+
{
|
|
1865
|
+
viaUsb: true,
|
|
1866
|
+
usbSessionId: session.sessionId
|
|
1867
|
+
}
|
|
1868
|
+
);
|
|
1932
1869
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1933
1870
|
record.hadUsbSession = true;
|
|
1934
1871
|
record.model = session.deviceInfo.modelName ?? session.deviceInfo.model ?? record.model;
|
|
@@ -1948,9 +1885,9 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1948
1885
|
* Probes already-authorized USB devices without a permission picker, then attaches and verifies
|
|
1949
1886
|
* the requested wallet if present.
|
|
1950
1887
|
*/
|
|
1951
|
-
async _tryUsbAttach(signal,
|
|
1888
|
+
async _tryUsbAttach(signal, expectedMasterFingerprint, options) {
|
|
1952
1889
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1953
|
-
if (!
|
|
1890
|
+
if (!expectedMasterFingerprint || this._forcedTransport === "qr" || !this._usbConnector) {
|
|
1954
1891
|
return void 0;
|
|
1955
1892
|
}
|
|
1956
1893
|
const maxAttempts = options?.waitForReenumeration ? KEYSTONE_USB_REATTACH_PROBE_ATTEMPTS : 1;
|
|
@@ -1981,28 +1918,15 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1981
1918
|
}
|
|
1982
1919
|
return void 0;
|
|
1983
1920
|
}
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
signal
|
|
1992
|
-
);
|
|
1993
|
-
_KeystoneAdapter._throwIfAborted(signal);
|
|
1994
|
-
if (!attached.success && attached.payload.code === HardwareErrorCode.DeviceBusyInternal) {
|
|
1995
|
-
throw createHwkError({
|
|
1996
|
-
...attached.payload,
|
|
1997
|
-
message: attached.payload.error
|
|
1998
|
-
});
|
|
1999
|
-
}
|
|
2000
|
-
if (attached.success) {
|
|
2001
|
-
record = this._devices.get(expectedWalletId);
|
|
2002
|
-
if (record) break;
|
|
2003
|
-
}
|
|
1921
|
+
const attached = await this._connectUsb({ expectedMasterFingerprint }, void 0, signal);
|
|
1922
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1923
|
+
if (!attached.success && attached.payload.code === HardwareErrorCode.DeviceBusyInternal) {
|
|
1924
|
+
throw createHwkError({
|
|
1925
|
+
...attached.payload,
|
|
1926
|
+
message: attached.payload.error
|
|
1927
|
+
});
|
|
2004
1928
|
}
|
|
2005
|
-
return
|
|
1929
|
+
return attached.success ? this._devices.get(expectedMasterFingerprint) : void 0;
|
|
2006
1930
|
}
|
|
2007
1931
|
/**
|
|
2008
1932
|
* Decides QR vs USB for one UR round trip. A pinned 'usb' with no live session fails closed;
|
|
@@ -2023,7 +1947,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2023
1947
|
releaseOperationRetention?.();
|
|
2024
1948
|
}
|
|
2025
1949
|
}
|
|
2026
|
-
async _resolveUrWithRoute(
|
|
1950
|
+
async _resolveUrWithRoute(callerRecord, requestUr, animated, operationId, signal, operationName) {
|
|
1951
|
+
let record = callerRecord;
|
|
2027
1952
|
let interactionRoute;
|
|
2028
1953
|
if (isHardwareOperationId2(operationId)) {
|
|
2029
1954
|
const operation = this._operations.resolve(operationId);
|
|
@@ -2037,9 +1962,9 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2037
1962
|
interactionRoute = route;
|
|
2038
1963
|
}
|
|
2039
1964
|
if (!interactionRoute && !this._forcedTransport && record && !record.usbSessionId && this._usbConnector) {
|
|
2040
|
-
await this._tryUsbAttach(signal, record.
|
|
1965
|
+
record = await this._tryUsbAttach(signal, record.masterFingerprint, {
|
|
2041
1966
|
waitForReenumeration: record.hadUsbSession
|
|
2042
|
-
});
|
|
1967
|
+
}) ?? record;
|
|
2043
1968
|
}
|
|
2044
1969
|
const wantUsb = interactionRoute ? interactionRoute.connectionType === "usb" : this._forcedTransport === "usb" || this._forcedTransport !== "qr" && Boolean(record?.usbSessionId);
|
|
2045
1970
|
if (wantUsb) {
|
|
@@ -2142,7 +2067,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2142
2067
|
const key = accountKey(hwkChain, syncPath);
|
|
2143
2068
|
let existingRecord = target.record;
|
|
2144
2069
|
if (!existingRecord) {
|
|
2145
|
-
existingRecord = await this._tryUsbAttach(signal, target.
|
|
2070
|
+
existingRecord = await this._tryUsbAttach(signal, target.expectedMasterFingerprint);
|
|
2146
2071
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
2147
2072
|
}
|
|
2148
2073
|
const booked = book?.get(key);
|
|
@@ -2150,14 +2075,14 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2150
2075
|
return { record: existingRecord, account: booked };
|
|
2151
2076
|
}
|
|
2152
2077
|
if (!operationConnectionType && existingRecord && !existingRecord.usbSessionId && this._forcedTransport === "usb") {
|
|
2153
|
-
await this._tryUsbAttach(signal, existingRecord.
|
|
2078
|
+
await this._tryUsbAttach(signal, existingRecord.masterFingerprint, {
|
|
2154
2079
|
waitForReenumeration: existingRecord.hadUsbSession
|
|
2155
2080
|
});
|
|
2156
2081
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
2157
|
-
existingRecord = this._devices.get(existingRecord.
|
|
2082
|
+
existingRecord = this._devices.get(existingRecord.masterFingerprint) ?? existingRecord;
|
|
2158
2083
|
}
|
|
2159
2084
|
const useSinglePathUsbExport = operationConnectionType ? operationConnectionType === "usb" : this._forcedTransport !== "qr" && Boolean(existingRecord?.usbSessionId);
|
|
2160
|
-
const schemas =
|
|
2085
|
+
const schemas = [keySchema(hwkChain, syncPath)];
|
|
2161
2086
|
const requestUr = this.urEngine.buildKeyDerivationRequest({ schemas, origin: this._origin });
|
|
2162
2087
|
const responseUr = await this._resolveUr(existingRecord, requestUr, false, connectId, signal);
|
|
2163
2088
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
@@ -2206,17 +2131,20 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2206
2131
|
async _ensureWalletKnown(connectId, deviceId, chain, signal) {
|
|
2207
2132
|
const target = this._resolveTarget(connectId, deviceId);
|
|
2208
2133
|
if (target.record) return { record: target.record };
|
|
2209
|
-
const attached = await this._tryUsbAttach(signal, target.
|
|
2134
|
+
const attached = await this._tryUsbAttach(signal, target.expectedMasterFingerprint);
|
|
2210
2135
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
2211
2136
|
if (attached) return { record: attached };
|
|
2137
|
+
if (target.expectedMasterFingerprint) {
|
|
2138
|
+
return { record: createDeviceRecord(target.expectedMasterFingerprint) };
|
|
2139
|
+
}
|
|
2212
2140
|
const { accountPath } = splitAccountPath(CHAIN_FINGERPRINT_PATHS[chain]);
|
|
2213
|
-
const
|
|
2214
|
-
|
|
2141
|
+
const requestUr = this.urEngine.buildKeyDerivationRequest({
|
|
2142
|
+
schemas: [keySchema(chain, accountPath)],
|
|
2143
|
+
origin: this._origin
|
|
2144
|
+
});
|
|
2215
2145
|
const responseUr = await this._resolveUr(void 0, requestUr, false, connectId, signal);
|
|
2216
2146
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
2217
|
-
|
|
2218
|
-
this._assertParsedIdentity(parsed, target);
|
|
2219
|
-
return { record: this._upsertDeviceRecord(parsed) };
|
|
2147
|
+
return { record: this._upsertDeviceRecord(this.urEngine.parseAccountResponse(responseUr)) };
|
|
2220
2148
|
}
|
|
2221
2149
|
/**
|
|
2222
2150
|
* The operation owning the running job, so a mid-call UI request can name it. Unpinned jobs map
|
|
@@ -2228,14 +2156,14 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2228
2156
|
if (isHardwareOperationId2(activeJobId)) return activeJobId;
|
|
2229
2157
|
return this._operationRouteForIdentifier(activeJobId)?.operationId;
|
|
2230
2158
|
}
|
|
2231
|
-
/** Routes are keyed by connectId; a job key may be the bare
|
|
2159
|
+
/** Routes are keyed by connectId; a job key may be the bare master fingerprint. */
|
|
2232
2160
|
_operationRouteForIdentifier(identifier) {
|
|
2233
2161
|
for (const key of keystoneCancelQueueKeys([identifier])) {
|
|
2234
2162
|
const route = this._operationRoutes.get(key);
|
|
2235
2163
|
if (route) return route;
|
|
2236
2164
|
}
|
|
2237
|
-
const
|
|
2238
|
-
return
|
|
2165
|
+
const masterFingerprint = keystoneMfpFromIdentifier(identifier);
|
|
2166
|
+
return masterFingerprint ? this._operationRoutes.get(walletConnectId(masterFingerprint)) : void 0;
|
|
2239
2167
|
}
|
|
2240
2168
|
/**
|
|
2241
2169
|
* A QR prompt has no transport to interrupt; releasing the registry slot on abort is what lets
|
|
@@ -2428,14 +2356,13 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2428
2356
|
}
|
|
2429
2357
|
};
|
|
2430
2358
|
export {
|
|
2359
|
+
KEYSTONE_COLD_START_PATH,
|
|
2431
2360
|
KEYSTONE_WALLET_CONNECT_ID_PREFIX,
|
|
2432
|
-
KEYSTONE_WALLET_ID_PATH,
|
|
2433
2361
|
KeystoneAdapter,
|
|
2434
2362
|
KeystoneUrEngine,
|
|
2435
2363
|
accountKey,
|
|
2436
2364
|
btcScriptTypeFromPath,
|
|
2437
2365
|
createDeviceRecord,
|
|
2438
|
-
deriveKeystoneWalletId,
|
|
2439
2366
|
normalizePath,
|
|
2440
2367
|
placeholderDeviceInfo,
|
|
2441
2368
|
splitAccountPath,
|