@onekeyfe/hwk-keystone-adapter 1.2.3-alpha.1 → 1.2.3-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 +10 -11
- package/dist/index.d.ts +10 -11
- package/dist/index.js +436 -515
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +438 -517
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -136,6 +136,11 @@ function fromSdkUr(ur) {
|
|
|
136
136
|
return { urType: ur.type, urData: ur.cbor.toString("hex") };
|
|
137
137
|
}
|
|
138
138
|
function splitSignature65(hex) {
|
|
139
|
+
if (hex.length !== 130) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Keystone returned a ${hex.length / 2}-byte signature; expected 65 bytes (r|s|v)`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
139
144
|
return { r: hex.slice(0, 64), s: hex.slice(64, 128), v: hex.slice(128) };
|
|
140
145
|
}
|
|
141
146
|
function requireBip32MasterFingerprint(value) {
|
|
@@ -439,7 +444,7 @@ import {
|
|
|
439
444
|
DEVICE,
|
|
440
445
|
DeviceJobQueue,
|
|
441
446
|
HardwareErrorCode,
|
|
442
|
-
|
|
447
|
+
OperationRegistry,
|
|
443
448
|
SDK,
|
|
444
449
|
TypedEventEmitter,
|
|
445
450
|
UI_REQUEST,
|
|
@@ -456,7 +461,7 @@ import {
|
|
|
456
461
|
getAllNetworkMethodChain,
|
|
457
462
|
hasHardwareRuntimeIdPrefix,
|
|
458
463
|
isAllNetworkMethodName,
|
|
459
|
-
|
|
464
|
+
isHardwareOperationId,
|
|
460
465
|
isHwkRecoveryHint,
|
|
461
466
|
operationMayHaveCompletedParams,
|
|
462
467
|
parseBip32MasterFingerprint as parseBip32MasterFingerprint2,
|
|
@@ -580,12 +585,8 @@ function placeholderDeviceInfo() {
|
|
|
580
585
|
var COLD_START_JOB_LABEL = "keystone-cold-start";
|
|
581
586
|
var KEYSTONE_USB_REATTACH_PROBE_ATTEMPTS = 4;
|
|
582
587
|
var KEYSTONE_USB_REATTACH_PROBE_INTERVAL_MS = 500;
|
|
583
|
-
function resolveHardwareOperationTarget(positionalTargetId,
|
|
584
|
-
const result = resolveGenericHardwareOperationTarget(
|
|
585
|
-
positionalTargetId,
|
|
586
|
-
interactionId,
|
|
587
|
-
"keystone"
|
|
588
|
-
);
|
|
588
|
+
function resolveHardwareOperationTarget(positionalTargetId, operationId) {
|
|
589
|
+
const result = resolveGenericHardwareOperationTarget(positionalTargetId, operationId, "keystone");
|
|
589
590
|
return result;
|
|
590
591
|
}
|
|
591
592
|
function waitForKeystoneUsbReattachProbe() {
|
|
@@ -593,10 +594,8 @@ function waitForKeystoneUsbReattachProbe() {
|
|
|
593
594
|
setTimeout(resolve, KEYSTONE_USB_REATTACH_PROBE_INTERVAL_MS);
|
|
594
595
|
});
|
|
595
596
|
}
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
const { code } = error;
|
|
599
|
-
return code === HardwareErrorCode.DeviceNotFound || code === HardwareErrorCode.DeviceDisconnected;
|
|
597
|
+
function getKeystoneJobId(connectId, deviceId) {
|
|
598
|
+
return isHardwareOperationId(connectId) ? connectId : deviceId || connectId || COLD_START_JOB_LABEL;
|
|
600
599
|
}
|
|
601
600
|
var BIP44_COIN_TYPE_TO_CHAIN = {
|
|
602
601
|
60: "evm",
|
|
@@ -612,20 +611,20 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
612
611
|
constructor(options) {
|
|
613
612
|
this.vendor = "keystone";
|
|
614
613
|
this.emitter = new TypedEventEmitter();
|
|
615
|
-
this.
|
|
616
|
-
this.
|
|
614
|
+
this._operationRoutes = /* @__PURE__ */ new Map();
|
|
615
|
+
this._operations = new OperationRegistry({
|
|
617
616
|
vendor: "keystone",
|
|
618
|
-
onEnded: (
|
|
619
|
-
const route = this.
|
|
620
|
-
if (route?.
|
|
621
|
-
this.
|
|
617
|
+
onEnded: (operation, reason) => {
|
|
618
|
+
const route = this._operationRoutes.get(operation.connectId);
|
|
619
|
+
if (route?.operationId === operation.operationId) {
|
|
620
|
+
this._operationRoutes.delete(operation.connectId);
|
|
622
621
|
}
|
|
623
|
-
this.emitter.emit(SDK.
|
|
624
|
-
type: SDK.
|
|
625
|
-
payload: {
|
|
622
|
+
this.emitter.emit(SDK.OPERATION_ENDED, {
|
|
623
|
+
type: SDK.OPERATION_ENDED,
|
|
624
|
+
payload: { operationId: operation.operationId, reason }
|
|
626
625
|
});
|
|
627
626
|
if (reason === "timeout") {
|
|
628
|
-
this.
|
|
627
|
+
this._releaseOperationConnection(operation).catch(() => void 0);
|
|
629
628
|
}
|
|
630
629
|
}
|
|
631
630
|
});
|
|
@@ -641,8 +640,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
641
640
|
this._handleUsbDisconnect = ({ connectId }) => {
|
|
642
641
|
const record = Array.from(this._devices.values()).find((item) => item.usbSessionId === connectId);
|
|
643
642
|
if (!record) return;
|
|
644
|
-
this.
|
|
645
|
-
this.
|
|
643
|
+
this._operations.endByConnectionKey(connectId, "disconnect");
|
|
644
|
+
this._operations.endByConnectionKey(record.connectId, "disconnect");
|
|
646
645
|
record.usbSessionId = void 0;
|
|
647
646
|
const info = toDeviceInfo(record);
|
|
648
647
|
if (record.qrSynced) {
|
|
@@ -660,10 +659,10 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
660
659
|
// there's exactly one implementation of each chain's address logic.
|
|
661
660
|
// ---------------------------------------------------------------------------
|
|
662
661
|
this.allNetworkGetAddress = async (connectId, deviceId, params) => {
|
|
663
|
-
const operationTarget = resolveHardwareOperationTarget(connectId, params.
|
|
662
|
+
const operationTarget = resolveHardwareOperationTarget(connectId, params.operationId);
|
|
664
663
|
if (!operationTarget.success) return operationTarget;
|
|
665
664
|
const effectiveConnectId = operationTarget.payload.targetId ?? "";
|
|
666
|
-
const {
|
|
665
|
+
const { operationId } = operationTarget.payload;
|
|
667
666
|
try {
|
|
668
667
|
const prefetched = await this._prefetchAllNetworkAccounts(
|
|
669
668
|
effectiveConnectId,
|
|
@@ -680,7 +679,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
680
679
|
const commonArgs = {
|
|
681
680
|
path: item.path,
|
|
682
681
|
showOnDevice: item.showOnDevice,
|
|
683
|
-
|
|
682
|
+
operationId
|
|
684
683
|
};
|
|
685
684
|
switch (method) {
|
|
686
685
|
case "evmGetAddress":
|
|
@@ -749,7 +748,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
749
748
|
return Promise.resolve();
|
|
750
749
|
}
|
|
751
750
|
async dispose() {
|
|
752
|
-
this.
|
|
751
|
+
this._operations.endAll("runtime-reset");
|
|
753
752
|
this._uiRegistry.cancel();
|
|
754
753
|
this._jobQueue.clear();
|
|
755
754
|
this._searchDeviceTargets.clear();
|
|
@@ -784,10 +783,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
784
783
|
}
|
|
785
784
|
const known = Array.from(this._devices.values()).map(toDeviceInfo);
|
|
786
785
|
if (options?.transportType === "qr") {
|
|
787
|
-
const searchTargetId = createHardwareSearchTargetId(
|
|
788
|
-
vendor: "keystone",
|
|
789
|
-
connectionType: "qr"
|
|
790
|
-
});
|
|
786
|
+
const searchTargetId = createHardwareSearchTargetId("keystone");
|
|
791
787
|
this._searchDeviceTargets.set(searchTargetId, "qr");
|
|
792
788
|
return [
|
|
793
789
|
{
|
|
@@ -835,7 +831,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
835
831
|
async _resetUsbSessions() {
|
|
836
832
|
await this._runUsbTeardown(async () => {
|
|
837
833
|
await this._usbConnectTail;
|
|
838
|
-
this.
|
|
834
|
+
this._operations.endAll("runtime-reset");
|
|
839
835
|
if (!this._usbConnector) return;
|
|
840
836
|
const sessionIds = new Set(
|
|
841
837
|
Array.from(this._devices.values()).map((record) => record.usbSessionId).filter((sessionId) => Boolean(sessionId))
|
|
@@ -914,18 +910,18 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
914
910
|
}
|
|
915
911
|
if (!connected.success) return connected;
|
|
916
912
|
const record = this._devices.get(connected.payload.deviceId);
|
|
917
|
-
this.
|
|
918
|
-
const
|
|
913
|
+
this._operations.endByConnectionKey(connected.payload.connectId, "explicit");
|
|
914
|
+
const operation = this._operations.create({
|
|
919
915
|
searchTargetId,
|
|
920
916
|
connectId: connected.payload.connectId,
|
|
921
917
|
device: connected.payload,
|
|
922
918
|
connectionKeys: selectedConnectionType === "usb" && record?.usbSessionId ? [record.usbSessionId] : []
|
|
923
919
|
});
|
|
924
|
-
this.
|
|
925
|
-
|
|
920
|
+
this._operationRoutes.set(connected.payload.connectId, {
|
|
921
|
+
operationId: operation.operationId,
|
|
926
922
|
connectionType: selectedConnectionType
|
|
927
923
|
});
|
|
928
|
-
return success(
|
|
924
|
+
return success(operation.operationId);
|
|
929
925
|
} catch (err) {
|
|
930
926
|
return this._errorToFailure(err);
|
|
931
927
|
}
|
|
@@ -937,25 +933,25 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
937
933
|
* QR-only (if it was ever QR-synced) or removes it entirely (pure-USB
|
|
938
934
|
* wallet that was never seen over QR) — see §4.2 of the design doc.
|
|
939
935
|
*/
|
|
940
|
-
async
|
|
941
|
-
const
|
|
942
|
-
if (!
|
|
943
|
-
this.
|
|
936
|
+
async releaseOperation(operationId) {
|
|
937
|
+
const operation = this._operations.find(operationId);
|
|
938
|
+
if (!operation) {
|
|
939
|
+
this._operations.resolve(operationId);
|
|
944
940
|
return;
|
|
945
941
|
}
|
|
946
|
-
const
|
|
947
|
-
if (!
|
|
948
|
-
await this.
|
|
942
|
+
const endedOperation = this._operations.end(operationId, "explicit");
|
|
943
|
+
if (!endedOperation) return;
|
|
944
|
+
await this._releaseOperationConnection(endedOperation);
|
|
949
945
|
}
|
|
950
|
-
async
|
|
951
|
-
const { connectId } =
|
|
946
|
+
async _releaseOperationConnection(operation) {
|
|
947
|
+
const { connectId } = operation;
|
|
952
948
|
let record;
|
|
953
949
|
try {
|
|
954
950
|
record = this._resolveTarget(connectId).record;
|
|
955
951
|
} catch {
|
|
956
952
|
return;
|
|
957
953
|
}
|
|
958
|
-
if (!record?.usbSessionId || !
|
|
954
|
+
if (!record?.usbSessionId || !operation.connectionKeys.includes(record.usbSessionId)) {
|
|
959
955
|
return;
|
|
960
956
|
}
|
|
961
957
|
const { usbSessionId } = record;
|
|
@@ -969,9 +965,9 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
969
965
|
this._handleUsbDisconnect({ connectId: usbSessionId });
|
|
970
966
|
});
|
|
971
967
|
}
|
|
972
|
-
getDeviceInfo(
|
|
968
|
+
getDeviceInfo(connectIdOrOperationId, deviceId) {
|
|
973
969
|
try {
|
|
974
|
-
const connectId =
|
|
970
|
+
const connectId = isHardwareOperationId(connectIdOrOperationId) ? this._operations.resolve(connectIdOrOperationId).connectId : connectIdOrOperationId;
|
|
975
971
|
const { record } = this._resolveTarget(connectId, deviceId);
|
|
976
972
|
if (!record) {
|
|
977
973
|
return Promise.resolve(
|
|
@@ -986,21 +982,26 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
986
982
|
return Promise.resolve(this._errorToFailure(err));
|
|
987
983
|
}
|
|
988
984
|
}
|
|
989
|
-
getSupportedChains() {
|
|
990
|
-
return ["evm", "btc", "sol", "tron"];
|
|
991
|
-
}
|
|
992
985
|
cancel(connectId) {
|
|
993
986
|
const reason = createHwkError({
|
|
994
987
|
code: HardwareErrorCode.UserAborted,
|
|
995
988
|
message: "User aborted operation"
|
|
996
989
|
});
|
|
997
|
-
this._uiRegistry.cancel();
|
|
998
990
|
const activeJobId = this._jobQueue.getActiveJob()?.deviceId;
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
991
|
+
if (connectId) {
|
|
992
|
+
if (!activeJobId || activeJobId !== connectId && activeJobId !== this._walletIdFromIdentifier(connectId)) {
|
|
993
|
+
this._jobQueue.cancelActiveAndPending(connectId, reason);
|
|
994
|
+
const walletId = this._walletIdFromIdentifier(connectId);
|
|
995
|
+
if (walletId && walletId !== connectId) {
|
|
996
|
+
this._jobQueue.cancelActiveAndPending(walletId, reason);
|
|
997
|
+
}
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
this._jobQueue.cancelActiveAndPending(activeJobId, reason);
|
|
1001
|
+
} else {
|
|
1002
|
+
this._jobQueue.cancelActiveAndPending(void 0, reason);
|
|
1003
|
+
}
|
|
1004
|
+
this._uiRegistry.cancel();
|
|
1004
1005
|
}
|
|
1005
1006
|
getChainFingerprint(connectId, deviceId, chain) {
|
|
1006
1007
|
try {
|
|
@@ -1063,7 +1064,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1063
1064
|
// EVM
|
|
1064
1065
|
// ---------------------------------------------------------------------------
|
|
1065
1066
|
async evmGetAddress(connectIdArg, deviceIdArg, paramsArg, book) {
|
|
1066
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1067
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1067
1068
|
if (!operationTarget.success) return operationTarget;
|
|
1068
1069
|
const connectId = operationTarget.payload.targetId;
|
|
1069
1070
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1079,37 +1080,34 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1079
1080
|
);
|
|
1080
1081
|
}
|
|
1081
1082
|
try {
|
|
1082
|
-
return await this._jobQueue.enqueue(
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
message: "Keystone did not return an extended public key for this account path"
|
|
1098
|
-
});
|
|
1099
|
-
}
|
|
1100
|
-
const address = this.urEngine.deriveEvmAddressFromXpub(
|
|
1101
|
-
account.extendedPublicKey,
|
|
1102
|
-
relativeDerivePath
|
|
1103
|
-
);
|
|
1104
|
-
return success({ address, path: normalizePath(params.path) });
|
|
1083
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1084
|
+
const { account } = await this._fetchAccount(
|
|
1085
|
+
connectId,
|
|
1086
|
+
deviceId,
|
|
1087
|
+
"evm",
|
|
1088
|
+
accountPath,
|
|
1089
|
+
signal,
|
|
1090
|
+
{ book }
|
|
1091
|
+
);
|
|
1092
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1093
|
+
if (!account.extendedPublicKey) {
|
|
1094
|
+
throw createHwkError({
|
|
1095
|
+
code: HardwareErrorCode.MethodNotSupported,
|
|
1096
|
+
message: "Keystone did not return an extended public key for this account path"
|
|
1097
|
+
});
|
|
1105
1098
|
}
|
|
1106
|
-
|
|
1099
|
+
const address = this.urEngine.deriveEvmAddressFromXpub(
|
|
1100
|
+
account.extendedPublicKey,
|
|
1101
|
+
relativeDerivePath
|
|
1102
|
+
);
|
|
1103
|
+
return success({ address, path: normalizePath(params.path) });
|
|
1104
|
+
});
|
|
1107
1105
|
} catch (err) {
|
|
1108
1106
|
return this._errorToFailure(err);
|
|
1109
1107
|
}
|
|
1110
1108
|
}
|
|
1111
1109
|
async evmSignTransaction(connectIdArg, deviceIdArg, paramsArg) {
|
|
1112
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1110
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1113
1111
|
if (!operationTarget.success) return operationTarget;
|
|
1114
1112
|
const connectId = operationTarget.payload.targetId;
|
|
1115
1113
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1128,45 +1126,42 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1128
1126
|
const rawTxHex = stripHex(params.serializedTx);
|
|
1129
1127
|
const path = normalizePath(params.path);
|
|
1130
1128
|
try {
|
|
1131
|
-
return await this._jobQueue.enqueue(
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
});
|
|
1162
|
-
}
|
|
1163
|
-
);
|
|
1129
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1130
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "evm", signal);
|
|
1131
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1132
|
+
const requestId = uuidv4();
|
|
1133
|
+
const dataType = parseInt(rawTxHex.slice(0, 2), 16) < 192 ? "typedTransaction" : "transaction";
|
|
1134
|
+
const requestUr = this.urEngine.buildEthSignRequest({
|
|
1135
|
+
requestId,
|
|
1136
|
+
unsignedTxHex: rawTxHex,
|
|
1137
|
+
dataType,
|
|
1138
|
+
path,
|
|
1139
|
+
xfp: record.masterFingerprint,
|
|
1140
|
+
chainId: params.chainId
|
|
1141
|
+
});
|
|
1142
|
+
const responseUr = await this._resolveUr(
|
|
1143
|
+
record,
|
|
1144
|
+
requestUr,
|
|
1145
|
+
true,
|
|
1146
|
+
connectId,
|
|
1147
|
+
signal,
|
|
1148
|
+
"evmSignTransaction"
|
|
1149
|
+
);
|
|
1150
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1151
|
+
const sig = this.urEngine.parseEthSignature(responseUr);
|
|
1152
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1153
|
+
return success({
|
|
1154
|
+
v: ensure0x(sig.v),
|
|
1155
|
+
r: ensure0x(sig.r),
|
|
1156
|
+
s: ensure0x(sig.s)
|
|
1157
|
+
});
|
|
1158
|
+
});
|
|
1164
1159
|
} catch (err) {
|
|
1165
1160
|
return this._errorToFailure(err);
|
|
1166
1161
|
}
|
|
1167
1162
|
}
|
|
1168
1163
|
async evmSignMessage(connectIdArg, deviceIdArg, paramsArg) {
|
|
1169
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1164
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1170
1165
|
if (!operationTarget.success) return operationTarget;
|
|
1171
1166
|
const connectId = operationTarget.payload.targetId;
|
|
1172
1167
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1181,40 +1176,37 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1181
1176
|
const messageHex = params.hex ? stripHex(params.message) : Buffer.from(params.message, "utf8").toString("hex");
|
|
1182
1177
|
const path = normalizePath(params.path);
|
|
1183
1178
|
try {
|
|
1184
|
-
return await this._jobQueue.enqueue(
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
return success({ signature: ensure0x(sig.r + sig.s + sig.v) });
|
|
1210
|
-
}
|
|
1211
|
-
);
|
|
1179
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1180
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "evm", signal);
|
|
1181
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1182
|
+
const requestId = uuidv4();
|
|
1183
|
+
const requestUr = this.urEngine.buildEthSignRequest({
|
|
1184
|
+
requestId,
|
|
1185
|
+
unsignedTxHex: messageHex,
|
|
1186
|
+
dataType: "personalMessage",
|
|
1187
|
+
path,
|
|
1188
|
+
xfp: record.masterFingerprint,
|
|
1189
|
+
chainId: params.chainId
|
|
1190
|
+
});
|
|
1191
|
+
const responseUr = await this._resolveUr(
|
|
1192
|
+
record,
|
|
1193
|
+
requestUr,
|
|
1194
|
+
true,
|
|
1195
|
+
connectId,
|
|
1196
|
+
signal,
|
|
1197
|
+
"evmSignMessage"
|
|
1198
|
+
);
|
|
1199
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1200
|
+
const sig = this.urEngine.parseEthSignature(responseUr);
|
|
1201
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1202
|
+
return success({ signature: ensure0x(sig.r + sig.s + sig.v) });
|
|
1203
|
+
});
|
|
1212
1204
|
} catch (err) {
|
|
1213
1205
|
return this._errorToFailure(err);
|
|
1214
1206
|
}
|
|
1215
1207
|
}
|
|
1216
1208
|
async evmSignTypedData(connectIdArg, deviceIdArg, paramsArg) {
|
|
1217
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1209
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1218
1210
|
if (!operationTarget.success) return operationTarget;
|
|
1219
1211
|
const connectId = operationTarget.payload.targetId;
|
|
1220
1212
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1230,37 +1222,37 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1230
1222
|
"Keystone always displays the full EIP-712 payload for on-device review \u2014 pre-hashed signing is not supported"
|
|
1231
1223
|
);
|
|
1232
1224
|
}
|
|
1233
|
-
const signDataHex = Buffer.from(
|
|
1225
|
+
const signDataHex = Buffer.from(
|
|
1226
|
+
params.dataJson ?? JSON.stringify(params.data),
|
|
1227
|
+
"utf8"
|
|
1228
|
+
).toString("hex");
|
|
1234
1229
|
const path = normalizePath(params.path);
|
|
1235
1230
|
try {
|
|
1236
|
-
return await this._jobQueue.enqueue(
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return success({ signature: ensure0x(sig.r + sig.s + sig.v) });
|
|
1262
|
-
}
|
|
1263
|
-
);
|
|
1231
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1232
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "evm", signal);
|
|
1233
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1234
|
+
const requestId = uuidv4();
|
|
1235
|
+
const requestUr = this.urEngine.buildEthSignRequest({
|
|
1236
|
+
requestId,
|
|
1237
|
+
unsignedTxHex: signDataHex,
|
|
1238
|
+
dataType: "typedData",
|
|
1239
|
+
path,
|
|
1240
|
+
xfp: record.masterFingerprint,
|
|
1241
|
+
chainId: params.chainId
|
|
1242
|
+
});
|
|
1243
|
+
const responseUr = await this._resolveUr(
|
|
1244
|
+
record,
|
|
1245
|
+
requestUr,
|
|
1246
|
+
true,
|
|
1247
|
+
connectId,
|
|
1248
|
+
signal,
|
|
1249
|
+
"evmSignTypedData"
|
|
1250
|
+
);
|
|
1251
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1252
|
+
const sig = this.urEngine.parseEthSignature(responseUr);
|
|
1253
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1254
|
+
return success({ signature: ensure0x(sig.r + sig.s + sig.v) });
|
|
1255
|
+
});
|
|
1264
1256
|
} catch (err) {
|
|
1265
1257
|
return this._errorToFailure(err);
|
|
1266
1258
|
}
|
|
@@ -1272,7 +1264,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1272
1264
|
// PSBT construction. Both are real, bounded follow-ups, not silent gaps.
|
|
1273
1265
|
// ---------------------------------------------------------------------------
|
|
1274
1266
|
async btcGetAddress(connectIdArg, deviceIdArg, paramsArg, book) {
|
|
1275
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1267
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1276
1268
|
if (!operationTarget.success) return operationTarget;
|
|
1277
1269
|
const connectId = operationTarget.payload.targetId;
|
|
1278
1270
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1305,32 +1297,29 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1305
1297
|
return failure(HardwareErrorCode.DevicePathForbidden, KEYSTONE_BTC_ACCOUNT_FORBIDDEN_MESSAGE);
|
|
1306
1298
|
}
|
|
1307
1299
|
try {
|
|
1308
|
-
return await this._jobQueue.enqueue(
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
message: "Keystone did not return an extended public key for this account path"
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
const address = this.urEngine.deriveBtcAddressFromXpub(
|
|
1327
|
-
account.extendedPublicKey,
|
|
1328
|
-
relativeDerivePath,
|
|
1329
|
-
scriptType
|
|
1330
|
-
);
|
|
1331
|
-
return success({ address, path: normalizedPath });
|
|
1300
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1301
|
+
const { account } = await this._fetchAccount(
|
|
1302
|
+
connectId,
|
|
1303
|
+
deviceId,
|
|
1304
|
+
"btc",
|
|
1305
|
+
accountPath,
|
|
1306
|
+
signal,
|
|
1307
|
+
{ book }
|
|
1308
|
+
);
|
|
1309
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1310
|
+
if (!account.extendedPublicKey) {
|
|
1311
|
+
throw createHwkError({
|
|
1312
|
+
code: HardwareErrorCode.MethodNotSupported,
|
|
1313
|
+
message: "Keystone did not return an extended public key for this account path"
|
|
1314
|
+
});
|
|
1332
1315
|
}
|
|
1333
|
-
|
|
1316
|
+
const address = this.urEngine.deriveBtcAddressFromXpub(
|
|
1317
|
+
account.extendedPublicKey,
|
|
1318
|
+
relativeDerivePath,
|
|
1319
|
+
scriptType
|
|
1320
|
+
);
|
|
1321
|
+
return success({ address, path: normalizedPath });
|
|
1322
|
+
});
|
|
1334
1323
|
} catch (err) {
|
|
1335
1324
|
return this._errorToFailure(err);
|
|
1336
1325
|
}
|
|
@@ -1345,7 +1334,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1345
1334
|
* this package doesn't wire in.
|
|
1346
1335
|
*/
|
|
1347
1336
|
async btcGetPublicKey(connectIdArg, deviceIdArg, paramsArg, book) {
|
|
1348
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1337
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1349
1338
|
if (!operationTarget.success) return operationTarget;
|
|
1350
1339
|
const connectId = operationTarget.payload.targetId;
|
|
1351
1340
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1364,35 +1353,32 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1364
1353
|
return failure(HardwareErrorCode.DevicePathForbidden, KEYSTONE_BTC_ACCOUNT_FORBIDDEN_MESSAGE);
|
|
1365
1354
|
}
|
|
1366
1355
|
try {
|
|
1367
|
-
return await this._jobQueue.enqueue(
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
code: HardwareErrorCode.MethodNotSupported,
|
|
1382
|
-
message: "Keystone did not return an extended public key for this account path"
|
|
1383
|
-
});
|
|
1384
|
-
}
|
|
1385
|
-
const meta = this.urEngine.parseXpubMeta(account.extendedPublicKey);
|
|
1386
|
-
return success({
|
|
1387
|
-
xpub: account.extendedPublicKey,
|
|
1388
|
-
publicKey: meta.publicKey,
|
|
1389
|
-
chainCode: meta.chainCode,
|
|
1390
|
-
depth: meta.depth,
|
|
1391
|
-
fingerprint: meta.parentFingerprint,
|
|
1392
|
-
path: normalizePath(accountPath)
|
|
1356
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1357
|
+
const { account } = await this._fetchAccount(
|
|
1358
|
+
connectId,
|
|
1359
|
+
deviceId,
|
|
1360
|
+
"btc",
|
|
1361
|
+
accountPath,
|
|
1362
|
+
signal,
|
|
1363
|
+
{ book }
|
|
1364
|
+
);
|
|
1365
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1366
|
+
if (!account.extendedPublicKey) {
|
|
1367
|
+
throw createHwkError({
|
|
1368
|
+
code: HardwareErrorCode.MethodNotSupported,
|
|
1369
|
+
message: "Keystone did not return an extended public key for this account path"
|
|
1393
1370
|
});
|
|
1394
1371
|
}
|
|
1395
|
-
|
|
1372
|
+
const meta = this.urEngine.parseXpubMeta(account.extendedPublicKey);
|
|
1373
|
+
return success({
|
|
1374
|
+
xpub: account.extendedPublicKey,
|
|
1375
|
+
publicKey: meta.publicKey,
|
|
1376
|
+
chainCode: meta.chainCode,
|
|
1377
|
+
depth: meta.depth,
|
|
1378
|
+
fingerprint: meta.parentFingerprint,
|
|
1379
|
+
path: normalizePath(accountPath)
|
|
1380
|
+
});
|
|
1381
|
+
});
|
|
1396
1382
|
} catch (err) {
|
|
1397
1383
|
return this._errorToFailure(err);
|
|
1398
1384
|
}
|
|
@@ -1404,7 +1390,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1404
1390
|
);
|
|
1405
1391
|
}
|
|
1406
1392
|
async btcSignPsbt(connectIdArg, deviceIdArg, paramsArg) {
|
|
1407
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1393
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1408
1394
|
if (!operationTarget.success) return operationTarget;
|
|
1409
1395
|
const connectId = operationTarget.payload.targetId;
|
|
1410
1396
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1416,31 +1402,28 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1416
1402
|
return failure(HardwareErrorCode.DevicePathForbidden, KEYSTONE_BTC_ACCOUNT_FORBIDDEN_MESSAGE);
|
|
1417
1403
|
}
|
|
1418
1404
|
try {
|
|
1419
|
-
return await this._jobQueue.enqueue(
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
return success({ signedPsbt });
|
|
1436
|
-
}
|
|
1437
|
-
);
|
|
1405
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1406
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "btc", signal);
|
|
1407
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1408
|
+
const requestUr = this.urEngine.buildBtcPsbtRequest(stripHex(params.psbt));
|
|
1409
|
+
const responseUr = await this._resolveUr(
|
|
1410
|
+
record,
|
|
1411
|
+
requestUr,
|
|
1412
|
+
true,
|
|
1413
|
+
connectId,
|
|
1414
|
+
signal,
|
|
1415
|
+
"btcSignPsbt"
|
|
1416
|
+
);
|
|
1417
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1418
|
+
const signedPsbt = this.urEngine.parseBtcPsbt(responseUr);
|
|
1419
|
+
return success({ signedPsbt });
|
|
1420
|
+
});
|
|
1438
1421
|
} catch (err) {
|
|
1439
1422
|
return this._errorToFailure(err);
|
|
1440
1423
|
}
|
|
1441
1424
|
}
|
|
1442
1425
|
async btcSignMessage(connectIdArg, deviceIdArg, paramsArg) {
|
|
1443
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1426
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1444
1427
|
if (!operationTarget.success) return operationTarget;
|
|
1445
1428
|
const connectId = operationTarget.payload.targetId;
|
|
1446
1429
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1458,48 +1441,42 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1458
1441
|
return failure(HardwareErrorCode.DevicePathForbidden, KEYSTONE_BTC_ACCOUNT_FORBIDDEN_MESSAGE);
|
|
1459
1442
|
}
|
|
1460
1443
|
try {
|
|
1461
|
-
return await this._jobQueue.enqueue(
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
return success({ signature: sig.signature });
|
|
1484
|
-
}
|
|
1485
|
-
);
|
|
1444
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1445
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "btc", signal);
|
|
1446
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1447
|
+
const requestId = uuidv4();
|
|
1448
|
+
const requestUr = this.urEngine.buildBtcMessageSignRequest({
|
|
1449
|
+
requestId,
|
|
1450
|
+
messageHex,
|
|
1451
|
+
accounts: [{ path, xfp: record.masterFingerprint }]
|
|
1452
|
+
});
|
|
1453
|
+
const responseUr = await this._resolveUr(
|
|
1454
|
+
record,
|
|
1455
|
+
requestUr,
|
|
1456
|
+
true,
|
|
1457
|
+
connectId,
|
|
1458
|
+
signal,
|
|
1459
|
+
"btcSignMessage"
|
|
1460
|
+
);
|
|
1461
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1462
|
+
const sig = this.urEngine.parseBtcSignature(responseUr);
|
|
1463
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1464
|
+
return success({ signature: sig.signature });
|
|
1465
|
+
});
|
|
1486
1466
|
} catch (err) {
|
|
1487
1467
|
return this._errorToFailure(err);
|
|
1488
1468
|
}
|
|
1489
1469
|
}
|
|
1490
1470
|
async btcGetMasterFingerprint(connectIdArg, deviceIdArg, paramsArg) {
|
|
1491
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1471
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1492
1472
|
if (!operationTarget.success) return operationTarget;
|
|
1493
1473
|
const connectId = operationTarget.payload.targetId;
|
|
1494
1474
|
const deviceId = deviceIdArg ?? void 0;
|
|
1495
1475
|
try {
|
|
1496
|
-
return await this._jobQueue.enqueue(
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
return success({ masterFingerprint: record.masterFingerprint });
|
|
1501
|
-
}
|
|
1502
|
-
);
|
|
1476
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1477
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "btc", signal);
|
|
1478
|
+
return success({ masterFingerprint: record.masterFingerprint });
|
|
1479
|
+
});
|
|
1503
1480
|
} catch (err) {
|
|
1504
1481
|
return this._errorToFailure(err);
|
|
1505
1482
|
}
|
|
@@ -1508,7 +1485,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1508
1485
|
// SOL
|
|
1509
1486
|
// ---------------------------------------------------------------------------
|
|
1510
1487
|
async solGetAddress(connectIdArg, deviceIdArg, paramsArg, book) {
|
|
1511
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1488
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1512
1489
|
if (!operationTarget.success) return operationTarget;
|
|
1513
1490
|
const connectId = operationTarget.payload.targetId;
|
|
1514
1491
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1518,23 +1495,20 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1518
1495
|
return failure(HardwareErrorCode.InvalidParams, "solGetAddress requires params.path");
|
|
1519
1496
|
const path = normalizePath(params.path);
|
|
1520
1497
|
try {
|
|
1521
|
-
return await this._jobQueue.enqueue(
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
return success({ address, path });
|
|
1530
|
-
}
|
|
1531
|
-
);
|
|
1498
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1499
|
+
const { account } = await this._fetchAccount(connectId, deviceId, "sol", path, signal, {
|
|
1500
|
+
book
|
|
1501
|
+
});
|
|
1502
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1503
|
+
const address = bs58.encode(Buffer.from(account.publicKey, "hex"));
|
|
1504
|
+
return success({ address, path });
|
|
1505
|
+
});
|
|
1532
1506
|
} catch (err) {
|
|
1533
1507
|
return this._errorToFailure(err);
|
|
1534
1508
|
}
|
|
1535
1509
|
}
|
|
1536
1510
|
async solSignTransaction(connectIdArg, deviceIdArg, paramsArg) {
|
|
1537
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1511
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1538
1512
|
if (!operationTarget.success) return operationTarget;
|
|
1539
1513
|
const connectId = operationTarget.payload.targetId;
|
|
1540
1514
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1549,39 +1523,36 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1549
1523
|
}
|
|
1550
1524
|
const path = normalizePath(params.path);
|
|
1551
1525
|
try {
|
|
1552
|
-
return await this._jobQueue.enqueue(
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
return success({ signature: sig.signature });
|
|
1577
|
-
}
|
|
1578
|
-
);
|
|
1526
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1527
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "sol", signal);
|
|
1528
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1529
|
+
const requestId = uuidv4();
|
|
1530
|
+
const requestUr = this.urEngine.buildSolSignRequest({
|
|
1531
|
+
requestId,
|
|
1532
|
+
unsignedPayloadHex: stripHex(params.serializedTx),
|
|
1533
|
+
dataType: "transaction",
|
|
1534
|
+
path,
|
|
1535
|
+
xfp: record.masterFingerprint
|
|
1536
|
+
});
|
|
1537
|
+
const responseUr = await this._resolveUr(
|
|
1538
|
+
record,
|
|
1539
|
+
requestUr,
|
|
1540
|
+
true,
|
|
1541
|
+
connectId,
|
|
1542
|
+
signal,
|
|
1543
|
+
"solSignTransaction"
|
|
1544
|
+
);
|
|
1545
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1546
|
+
const sig = this.urEngine.parseSolSignature(responseUr);
|
|
1547
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1548
|
+
return success({ signature: sig.signature });
|
|
1549
|
+
});
|
|
1579
1550
|
} catch (err) {
|
|
1580
1551
|
return this._errorToFailure(err);
|
|
1581
1552
|
}
|
|
1582
1553
|
}
|
|
1583
1554
|
async solSignMessage(connectIdArg, deviceIdArg, paramsArg) {
|
|
1584
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1555
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1585
1556
|
if (!operationTarget.success) return operationTarget;
|
|
1586
1557
|
const connectId = operationTarget.payload.targetId;
|
|
1587
1558
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1595,33 +1566,30 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1595
1566
|
}
|
|
1596
1567
|
const path = normalizePath(params.path);
|
|
1597
1568
|
try {
|
|
1598
|
-
return await this._jobQueue.enqueue(
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return success({ signature: sig.signature });
|
|
1623
|
-
}
|
|
1624
|
-
);
|
|
1569
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1570
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "sol", signal);
|
|
1571
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1572
|
+
const requestId = uuidv4();
|
|
1573
|
+
const requestUr = this.urEngine.buildSolSignRequest({
|
|
1574
|
+
requestId,
|
|
1575
|
+
unsignedPayloadHex: stripHex(params.message),
|
|
1576
|
+
dataType: "message",
|
|
1577
|
+
path,
|
|
1578
|
+
xfp: record.masterFingerprint
|
|
1579
|
+
});
|
|
1580
|
+
const responseUr = await this._resolveUr(
|
|
1581
|
+
record,
|
|
1582
|
+
requestUr,
|
|
1583
|
+
true,
|
|
1584
|
+
connectId,
|
|
1585
|
+
signal,
|
|
1586
|
+
"solSignMessage"
|
|
1587
|
+
);
|
|
1588
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1589
|
+
const sig = this.urEngine.parseSolSignature(responseUr);
|
|
1590
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1591
|
+
return success({ signature: sig.signature });
|
|
1592
|
+
});
|
|
1625
1593
|
} catch (err) {
|
|
1626
1594
|
return this._errorToFailure(err);
|
|
1627
1595
|
}
|
|
@@ -1634,7 +1602,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1634
1602
|
// unverified response semantics).
|
|
1635
1603
|
// ---------------------------------------------------------------------------
|
|
1636
1604
|
async tronGetAddress(connectIdArg, deviceIdArg, paramsArg, book) {
|
|
1637
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1605
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1638
1606
|
if (!operationTarget.success) return operationTarget;
|
|
1639
1607
|
const connectId = operationTarget.payload.targetId;
|
|
1640
1608
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1650,37 +1618,34 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1650
1618
|
);
|
|
1651
1619
|
}
|
|
1652
1620
|
try {
|
|
1653
|
-
return await this._jobQueue.enqueue(
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
message: "Keystone did not return an extended public key for this account path"
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
const address = this.urEngine.deriveTronAddressFromXpub(
|
|
1672
|
-
account.extendedPublicKey,
|
|
1673
|
-
relativeDerivePath
|
|
1674
|
-
);
|
|
1675
|
-
return success({ address, path: normalizePath(params.path) });
|
|
1621
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1622
|
+
const { account } = await this._fetchAccount(
|
|
1623
|
+
connectId,
|
|
1624
|
+
deviceId,
|
|
1625
|
+
"tron",
|
|
1626
|
+
accountPath,
|
|
1627
|
+
signal,
|
|
1628
|
+
{ book }
|
|
1629
|
+
);
|
|
1630
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1631
|
+
if (!account.extendedPublicKey) {
|
|
1632
|
+
throw createHwkError({
|
|
1633
|
+
code: HardwareErrorCode.MethodNotSupported,
|
|
1634
|
+
message: "Keystone did not return an extended public key for this account path"
|
|
1635
|
+
});
|
|
1676
1636
|
}
|
|
1677
|
-
|
|
1637
|
+
const address = this.urEngine.deriveTronAddressFromXpub(
|
|
1638
|
+
account.extendedPublicKey,
|
|
1639
|
+
relativeDerivePath
|
|
1640
|
+
);
|
|
1641
|
+
return success({ address, path: normalizePath(params.path) });
|
|
1642
|
+
});
|
|
1678
1643
|
} catch (err) {
|
|
1679
1644
|
return this._errorToFailure(err);
|
|
1680
1645
|
}
|
|
1681
1646
|
}
|
|
1682
1647
|
async tronSignTransaction(connectIdArg, deviceIdArg, paramsArg) {
|
|
1683
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1648
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1684
1649
|
if (!operationTarget.success) return operationTarget;
|
|
1685
1650
|
const connectId = operationTarget.payload.targetId;
|
|
1686
1651
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1699,38 +1664,35 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1699
1664
|
const rawTxHex = stripHex(params.rawTxHex);
|
|
1700
1665
|
const path = normalizePath(params.path);
|
|
1701
1666
|
try {
|
|
1702
|
-
return await this._jobQueue.enqueue(
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
return success({ signature: sig.signature });
|
|
1726
|
-
}
|
|
1727
|
-
);
|
|
1667
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1668
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "tron", signal);
|
|
1669
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1670
|
+
const requestId = uuidv4();
|
|
1671
|
+
const requestUr = this.urEngine.buildTronSignRequest({
|
|
1672
|
+
requestId,
|
|
1673
|
+
rawTxHex,
|
|
1674
|
+
path,
|
|
1675
|
+
xfp: record.masterFingerprint
|
|
1676
|
+
});
|
|
1677
|
+
const responseUr = await this._resolveUr(
|
|
1678
|
+
record,
|
|
1679
|
+
requestUr,
|
|
1680
|
+
true,
|
|
1681
|
+
connectId,
|
|
1682
|
+
signal,
|
|
1683
|
+
"tronSignTransaction"
|
|
1684
|
+
);
|
|
1685
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1686
|
+
const sig = this.urEngine.parseTronSignature(responseUr);
|
|
1687
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1688
|
+
return success({ signature: sig.signature });
|
|
1689
|
+
});
|
|
1728
1690
|
} catch (err) {
|
|
1729
1691
|
return this._errorToFailure(err);
|
|
1730
1692
|
}
|
|
1731
1693
|
}
|
|
1732
1694
|
async tronSignMessage(connectIdArg, deviceIdArg, paramsArg) {
|
|
1733
|
-
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.
|
|
1695
|
+
const operationTarget = resolveHardwareOperationTarget(connectIdArg, paramsArg?.operationId);
|
|
1734
1696
|
if (!operationTarget.success) return operationTarget;
|
|
1735
1697
|
const connectId = operationTarget.payload.targetId;
|
|
1736
1698
|
const deviceId = deviceIdArg ?? void 0;
|
|
@@ -1751,33 +1713,30 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1751
1713
|
const messageHex = stripHex(params.messageHex);
|
|
1752
1714
|
const path = normalizePath(params.path);
|
|
1753
1715
|
try {
|
|
1754
|
-
return await this._jobQueue.enqueue(
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
return success({ signature: sig.signature });
|
|
1779
|
-
}
|
|
1780
|
-
);
|
|
1716
|
+
return await this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1717
|
+
const { record } = await this._ensureWalletKnown(connectId, deviceId, "tron", signal);
|
|
1718
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1719
|
+
const requestId = uuidv4();
|
|
1720
|
+
const requestUr = this.urEngine.buildTronSignRequest({
|
|
1721
|
+
requestId,
|
|
1722
|
+
rawTxHex: messageHex,
|
|
1723
|
+
path,
|
|
1724
|
+
xfp: record.masterFingerprint,
|
|
1725
|
+
signType: 2 /* PersonalMessage */
|
|
1726
|
+
});
|
|
1727
|
+
const responseUr = await this._resolveUr(
|
|
1728
|
+
record,
|
|
1729
|
+
requestUr,
|
|
1730
|
+
true,
|
|
1731
|
+
connectId,
|
|
1732
|
+
signal,
|
|
1733
|
+
"tronSignMessage"
|
|
1734
|
+
);
|
|
1735
|
+
_KeystoneAdapter._throwIfAborted(signal);
|
|
1736
|
+
const sig = this.urEngine.parseTronSignature(responseUr);
|
|
1737
|
+
_KeystoneAdapter._assertRequestIdMatches(requestId, sig.requestId);
|
|
1738
|
+
return success({ signature: sig.signature });
|
|
1739
|
+
});
|
|
1781
1740
|
} catch (err) {
|
|
1782
1741
|
return this._errorToFailure(err);
|
|
1783
1742
|
}
|
|
@@ -1816,7 +1775,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1816
1775
|
* one-path-at-a-time export flow because the device limits that channel.
|
|
1817
1776
|
*/
|
|
1818
1777
|
async _prefetchAllNetworkAccounts(connectId, deviceId, params) {
|
|
1819
|
-
return this._jobQueue.enqueue(
|
|
1778
|
+
return this._jobQueue.enqueue(getKeystoneJobId(connectId, deviceId), async (signal) => {
|
|
1820
1779
|
const target = this._resolveTarget(connectId, deviceId);
|
|
1821
1780
|
const { record: targetRecord } = target;
|
|
1822
1781
|
let record = targetRecord;
|
|
@@ -1837,19 +1796,29 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1837
1796
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
1838
1797
|
}
|
|
1839
1798
|
if (this._forcedTransport !== "qr" && record?.usbSessionId) {
|
|
1799
|
+
const bundleSessionId = record.usbSessionId;
|
|
1800
|
+
const assertBundleSession = () => {
|
|
1801
|
+
if (record?.usbSessionId !== bundleSessionId) {
|
|
1802
|
+
throw createHwkError({
|
|
1803
|
+
code: HardwareErrorCode.TransportNotAvailable,
|
|
1804
|
+
message: "Keystone USB connection was lost during account export"
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1840
1808
|
const missingSchemas2 = Array.from(requestedByKey.values());
|
|
1841
|
-
for (const
|
|
1809
|
+
for (const schema of missingSchemas2) {
|
|
1842
1810
|
if (!book.has(accountKey(schema.hwkChain, schema.path))) {
|
|
1811
|
+
assertBundleSession();
|
|
1843
1812
|
const synced = await this._fetchAccount(
|
|
1844
1813
|
connectId,
|
|
1845
1814
|
deviceId,
|
|
1846
1815
|
schema.hwkChain,
|
|
1847
1816
|
schema.path,
|
|
1848
1817
|
signal,
|
|
1849
|
-
{
|
|
1818
|
+
{ book }
|
|
1850
1819
|
);
|
|
1851
1820
|
record = synced.record;
|
|
1852
|
-
|
|
1821
|
+
assertBundleSession();
|
|
1853
1822
|
}
|
|
1854
1823
|
}
|
|
1855
1824
|
for (const schema of missingSchemas2) {
|
|
@@ -1918,8 +1887,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1918
1887
|
*/
|
|
1919
1888
|
_resolveTarget(connectId, deviceId) {
|
|
1920
1889
|
let resolvedConnectId = connectId;
|
|
1921
|
-
if (
|
|
1922
|
-
resolvedConnectId = this.
|
|
1890
|
+
if (isHardwareOperationId(connectId)) {
|
|
1891
|
+
resolvedConnectId = this._operations.resolve(connectId).connectId;
|
|
1923
1892
|
}
|
|
1924
1893
|
const identifiers = [deviceId, resolvedConnectId].filter(
|
|
1925
1894
|
(identifier) => Boolean(identifier)
|
|
@@ -1975,7 +1944,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
1975
1944
|
* already has a live session, so this must NOT unconditionally mark
|
|
1976
1945
|
* `qrSynced`, or a USB-only wallet would wrongly survive a later USB
|
|
1977
1946
|
* disconnect as a "QR-synced, demote to QR-only" entry instead of being
|
|
1978
|
-
* dropped outright (see `
|
|
1947
|
+
* dropped outright (see `releaseOperation`).
|
|
1979
1948
|
*/
|
|
1980
1949
|
_upsertDeviceRecord(parsed, options) {
|
|
1981
1950
|
const walletId = deriveKeystoneWalletId(parsed.accounts);
|
|
@@ -2113,7 +2082,7 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2113
2082
|
* then attach and verify the requested wallet when one is present. This is
|
|
2114
2083
|
* used both after an adapter restart and after a QR-only period, so plugging
|
|
2115
2084
|
* USB back in affects the next business call without changing an in-flight
|
|
2116
|
-
* QR
|
|
2085
|
+
* QR operation.
|
|
2117
2086
|
*/
|
|
2118
2087
|
async _tryUsbAttach(expectedWalletId, expectedMasterFingerprint, options) {
|
|
2119
2088
|
if (!expectedWalletId || this._forcedTransport === "qr" || !this._usbConnector) {
|
|
@@ -2167,32 +2136,32 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2167
2136
|
* `switchTransport('usb')` on a wallet with no live USB session fails
|
|
2168
2137
|
* closed rather than silently falling back to QR.
|
|
2169
2138
|
*/
|
|
2170
|
-
async _resolveUr(record, requestUr, animated,
|
|
2171
|
-
const
|
|
2139
|
+
async _resolveUr(record, requestUr, animated, operationId, signal, operationName) {
|
|
2140
|
+
const releaseOperationRetention = isHardwareOperationId(operationId) ? this._operations.retain(operationId) : void 0;
|
|
2172
2141
|
try {
|
|
2173
2142
|
return await this._resolveUrWithRoute(
|
|
2174
2143
|
record,
|
|
2175
2144
|
requestUr,
|
|
2176
2145
|
animated,
|
|
2177
|
-
|
|
2146
|
+
operationId,
|
|
2178
2147
|
signal,
|
|
2179
2148
|
operationName
|
|
2180
2149
|
);
|
|
2181
2150
|
} finally {
|
|
2182
|
-
|
|
2151
|
+
releaseOperationRetention?.();
|
|
2183
2152
|
}
|
|
2184
2153
|
}
|
|
2185
|
-
async _resolveUrWithRoute(record, requestUr, animated,
|
|
2154
|
+
async _resolveUrWithRoute(record, requestUr, animated, operationId, signal, operationName) {
|
|
2186
2155
|
let interactionRoute;
|
|
2187
|
-
if (
|
|
2188
|
-
const
|
|
2189
|
-
const route = this.
|
|
2190
|
-
if (!route || route.
|
|
2191
|
-
this.
|
|
2156
|
+
if (isHardwareOperationId(operationId)) {
|
|
2157
|
+
const operation = this._operations.resolve(operationId);
|
|
2158
|
+
const route = this._operationRoutes.get(operation.connectId);
|
|
2159
|
+
if (!route || route.operationId !== operationId) {
|
|
2160
|
+
this._operations.end(operationId, "disconnect");
|
|
2192
2161
|
throw createHwkError({
|
|
2193
|
-
code: HardwareErrorCode.
|
|
2194
|
-
message: "Keystone hardware
|
|
2195
|
-
params: {
|
|
2162
|
+
code: HardwareErrorCode.OperationEnded,
|
|
2163
|
+
message: "Keystone hardware operation is no longer connected",
|
|
2164
|
+
params: { operationId, reason: "disconnect" }
|
|
2196
2165
|
});
|
|
2197
2166
|
}
|
|
2198
2167
|
interactionRoute = route;
|
|
@@ -2206,12 +2175,12 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2206
2175
|
if (wantUsb) {
|
|
2207
2176
|
if (!record?.usbSessionId || !this._usbConnector) {
|
|
2208
2177
|
if (interactionRoute) {
|
|
2209
|
-
this.
|
|
2178
|
+
this._operations.end(interactionRoute.operationId, "disconnect");
|
|
2210
2179
|
throw createHwkError({
|
|
2211
|
-
code: HardwareErrorCode.
|
|
2212
|
-
message: "Keystone
|
|
2180
|
+
code: HardwareErrorCode.OperationEnded,
|
|
2181
|
+
message: "Keystone operation USB connection was lost",
|
|
2213
2182
|
params: {
|
|
2214
|
-
|
|
2183
|
+
operationId: interactionRoute.operationId,
|
|
2215
2184
|
reason: "disconnect"
|
|
2216
2185
|
}
|
|
2217
2186
|
});
|
|
@@ -2246,16 +2215,16 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2246
2215
|
}
|
|
2247
2216
|
record.usbSessionId = void 0;
|
|
2248
2217
|
if (interactionRoute) {
|
|
2249
|
-
this.
|
|
2218
|
+
this._operations.end(interactionRoute.operationId, "disconnect");
|
|
2250
2219
|
throw createHwkError({
|
|
2251
|
-
code: HardwareErrorCode.
|
|
2252
|
-
message: operationName ? `Keystone ${operationName} may have completed before the USB connection was lost` : "Keystone
|
|
2220
|
+
code: HardwareErrorCode.OperationEnded,
|
|
2221
|
+
message: operationName ? `Keystone ${operationName} may have completed before the USB connection was lost` : "Keystone operation USB connection was lost",
|
|
2253
2222
|
recovery: operationName ? { scope: "unknown" } : void 0,
|
|
2254
2223
|
params: operationName ? operationMayHaveCompletedParams(operationName, {
|
|
2255
|
-
|
|
2224
|
+
operationId: interactionRoute.operationId,
|
|
2256
2225
|
reason: "disconnect"
|
|
2257
2226
|
}) : {
|
|
2258
|
-
|
|
2227
|
+
operationId: interactionRoute.operationId,
|
|
2259
2228
|
reason: "disconnect"
|
|
2260
2229
|
}
|
|
2261
2230
|
});
|
|
@@ -2294,8 +2263,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2294
2263
|
/**
|
|
2295
2264
|
* Fetch one account's key material from the device for this operation only.
|
|
2296
2265
|
* `book` lets earlier fetches of the same operation be reused; nothing is
|
|
2297
|
-
* retained on the record.
|
|
2298
|
-
*
|
|
2266
|
+
* retained on the record. A failed USB export ends this operation without
|
|
2267
|
+
* replaying the request or switching transports.
|
|
2299
2268
|
*/
|
|
2300
2269
|
async _fetchAccount(connectId, deviceId, hwkChain, syncPath, signal, options) {
|
|
2301
2270
|
const target = this._resolveTarget(connectId, deviceId);
|
|
@@ -2330,56 +2299,8 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2330
2299
|
})),
|
|
2331
2300
|
origin: this._origin
|
|
2332
2301
|
});
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
try {
|
|
2336
|
-
responseUr = await this._resolveUr(existingRecord, requestUr, false, connectId, signal);
|
|
2337
|
-
} catch (error) {
|
|
2338
|
-
if (isHardwareInteractionId(connectId) || !useSinglePathUsbExport || !isKeystoneUsbReconnectableError(error)) {
|
|
2339
|
-
throw error;
|
|
2340
|
-
}
|
|
2341
|
-
await waitForKeystoneUsbReattachProbe();
|
|
2342
|
-
_KeystoneAdapter._throwIfAborted(signal);
|
|
2343
|
-
const recoveredRecord = await this._tryUsbAttach(
|
|
2344
|
-
existingRecord?.walletId,
|
|
2345
|
-
existingRecord?.masterFingerprint,
|
|
2346
|
-
{ waitForReenumeration: true }
|
|
2347
|
-
);
|
|
2348
|
-
_KeystoneAdapter._throwIfAborted(signal);
|
|
2349
|
-
if (recoveredRecord?.usbSessionId) {
|
|
2350
|
-
try {
|
|
2351
|
-
responseUr = await this._resolveUr(recoveredRecord, requestUr, false, connectId, signal);
|
|
2352
|
-
existingRecord = recoveredRecord;
|
|
2353
|
-
} catch (retryError) {
|
|
2354
|
-
if (!isKeystoneUsbReconnectableError(retryError)) throw retryError;
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
if (!responseUr) {
|
|
2358
|
-
if (this._forcedTransport === "usb") throw error;
|
|
2359
|
-
const fallbackSchemaPaths = options?.qrFallbackSchemaPaths ?? [
|
|
2360
|
-
{ hwkChain, path: syncPath }
|
|
2361
|
-
];
|
|
2362
|
-
const qrFallbackSchemas = [
|
|
2363
|
-
{ hwkChain: "evm", path: KEYSTONE_WALLET_ID_PATH },
|
|
2364
|
-
...fallbackSchemaPaths.filter(
|
|
2365
|
-
(schema) => normalizePath(schema.path) !== KEYSTONE_WALLET_ID_PATH
|
|
2366
|
-
)
|
|
2367
|
-
].map((schema) => ({
|
|
2368
|
-
path: schema.path,
|
|
2369
|
-
curve: schema.hwkChain === "sol" ? "ed25519" : "secp256k1"
|
|
2370
|
-
}));
|
|
2371
|
-
const qrRequestUr = this.urEngine.buildKeyDerivationRequest({
|
|
2372
|
-
schemas: qrFallbackSchemas,
|
|
2373
|
-
origin: this._origin
|
|
2374
|
-
});
|
|
2375
|
-
const displayDevice = existingRecord ? toDeviceInfo(existingRecord) : placeholderDeviceInfo();
|
|
2376
|
-
responseUr = await this._requestQrDisplayAndAwaitResponse(displayDevice, {
|
|
2377
|
-
...qrRequestUr,
|
|
2378
|
-
animated: false
|
|
2379
|
-
});
|
|
2380
|
-
resolvedViaUsb = false;
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2302
|
+
const resolvedViaUsb = useSinglePathUsbExport;
|
|
2303
|
+
const responseUr = await this._resolveUr(existingRecord, requestUr, false, connectId, signal);
|
|
2383
2304
|
_KeystoneAdapter._throwIfAborted(signal);
|
|
2384
2305
|
const parsed = this.urEngine.parseAccountResponse(responseUr);
|
|
2385
2306
|
let record;
|
|
@@ -2608,13 +2529,13 @@ var KeystoneAdapter = class _KeystoneAdapter {
|
|
|
2608
2529
|
if (e._tag === UI_REQUEST_CANCELLED_TAG || e._tag === UI_REQUEST_PREEMPTED_TAG) {
|
|
2609
2530
|
return failure(
|
|
2610
2531
|
HardwareErrorCode.UserAborted,
|
|
2611
|
-
e.message ?? "Keystone QR
|
|
2532
|
+
e.message ?? "Keystone QR operation was cancelled"
|
|
2612
2533
|
);
|
|
2613
2534
|
}
|
|
2614
2535
|
if (e._tag === UI_REQUEST_TIMEOUT_TAG) {
|
|
2615
2536
|
return failure(
|
|
2616
2537
|
HardwareErrorCode.OperationTimeout,
|
|
2617
|
-
e.message ?? "Keystone QR
|
|
2538
|
+
e.message ?? "Keystone QR operation timed out"
|
|
2618
2539
|
);
|
|
2619
2540
|
}
|
|
2620
2541
|
}
|