@metamask-previews/eth-qr-keyring 1.0.0-065a890
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/CHANGELOG.md +1 -0
- package/LICENSE +15 -0
- package/README.md +1 -0
- package/dist/airgapped-signer.cjs +242 -0
- package/dist/airgapped-signer.cjs.map +1 -0
- package/dist/airgapped-signer.d.cts +132 -0
- package/dist/airgapped-signer.d.cts.map +1 -0
- package/dist/airgapped-signer.d.mts +132 -0
- package/dist/airgapped-signer.d.mts.map +1 -0
- package/dist/airgapped-signer.mjs +242 -0
- package/dist/airgapped-signer.mjs.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/dist/qr-keyring-bridge.cjs +36 -0
- package/dist/qr-keyring-bridge.cjs.map +1 -0
- package/dist/qr-keyring-bridge.d.cts +25 -0
- package/dist/qr-keyring-bridge.d.cts.map +1 -0
- package/dist/qr-keyring-bridge.d.mts +25 -0
- package/dist/qr-keyring-bridge.d.mts.map +1 -0
- package/dist/qr-keyring-bridge.mjs +32 -0
- package/dist/qr-keyring-bridge.mjs.map +1 -0
- package/dist/qr-keyring.cjs +238 -0
- package/dist/qr-keyring.cjs.map +1 -0
- package/dist/qr-keyring.d.cts +121 -0
- package/dist/qr-keyring.d.cts.map +1 -0
- package/dist/qr-keyring.d.mts +121 -0
- package/dist/qr-keyring.d.mts.map +1 -0
- package/dist/qr-keyring.mjs +233 -0
- package/dist/qr-keyring.mjs.map +1 -0
- package/package.json +94 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Changelog
|
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 MetaMask
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# QR Keyring
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _AirgappedSigner_instances, _AirgappedSigner_source, _AirgappedSigner_initFromUR, _AirgappedSigner_decodeUR;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.AirgappedSigner = exports.KeyringMode = exports.SUPPORTED_UR_TYPE = void 0;
|
|
19
|
+
const util_1 = require("@ethereumjs/util");
|
|
20
|
+
const bc_ur_registry_eth_1 = require("@keystonehq/bc-ur-registry-eth");
|
|
21
|
+
const utils_1 = require("@metamask/utils");
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
23
|
+
const hdkey_1 = __importDefault(require("hdkey"));
|
|
24
|
+
exports.SUPPORTED_UR_TYPE = {
|
|
25
|
+
CRYPTO_HDKEY: 'crypto-hdkey',
|
|
26
|
+
CRYPTO_ACCOUNT: 'crypto-account',
|
|
27
|
+
ETH_SIGNATURE: 'eth-signature',
|
|
28
|
+
};
|
|
29
|
+
var KeyringMode;
|
|
30
|
+
(function (KeyringMode) {
|
|
31
|
+
KeyringMode["HD"] = "hd";
|
|
32
|
+
KeyringMode["ACCOUNT"] = "account";
|
|
33
|
+
})(KeyringMode || (exports.KeyringMode = KeyringMode = {}));
|
|
34
|
+
const DEFAULT_CHILDREN_PATH = '0/*';
|
|
35
|
+
const MAX_INDEX = 1000;
|
|
36
|
+
/**
|
|
37
|
+
* Get the fingerprint of the source CryptoAccount or CryptoHDKey
|
|
38
|
+
*
|
|
39
|
+
* @param source - The source CryptoAccount or CryptoHDKey
|
|
40
|
+
* @returns The fingerprint of the source
|
|
41
|
+
*/
|
|
42
|
+
function getFingerprintFromSource(source) {
|
|
43
|
+
return source instanceof bc_ur_registry_eth_1.CryptoAccount
|
|
44
|
+
? source.getMasterFingerprint()?.toString('hex')
|
|
45
|
+
: source.getParentFingerprint()?.toString('hex');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get fingerprint, account paths and names from the a CryptoAccount
|
|
49
|
+
*
|
|
50
|
+
* Note: This function emulates the behavior of the `@keystonehq/base-eth-keyring`
|
|
51
|
+
* library when dealing with CryptoAccount objects (for backwards compatibility
|
|
52
|
+
* reasons). Though, the way it retrieves `name` and `keyringAccount` is questionable,
|
|
53
|
+
* as `name` and `keyringAccount` are updated after each descriptor discovery, effectively
|
|
54
|
+
* returning the last descriptor's `name` and `keyringAccount`.
|
|
55
|
+
*
|
|
56
|
+
* @param source - The source CryptoAccount
|
|
57
|
+
* @returns The paths
|
|
58
|
+
*/
|
|
59
|
+
function readCryptoAccountOutputDescriptors(source) {
|
|
60
|
+
const descriptors = source.getOutputDescriptors();
|
|
61
|
+
if (!descriptors || descriptors.length === 0) {
|
|
62
|
+
throw new Error('No output descriptors found in CryptoAccount');
|
|
63
|
+
}
|
|
64
|
+
let name = '';
|
|
65
|
+
let keyringAccount = '';
|
|
66
|
+
const paths = descriptors.reduce((descriptorsPaths, current) => {
|
|
67
|
+
const hdKey = current.getHDKey();
|
|
68
|
+
if (hdKey) {
|
|
69
|
+
const path = `M/${hdKey.getOrigin().getPath()}`;
|
|
70
|
+
const address = (0, utils_1.getChecksumAddress)((0, utils_1.add0x)(Buffer.from((0, util_1.publicToAddress)(hdKey.getKey(), true)).toString('hex')));
|
|
71
|
+
descriptorsPaths[address] = path;
|
|
72
|
+
name = hdKey.getName();
|
|
73
|
+
keyringAccount = hdKey.getNote();
|
|
74
|
+
}
|
|
75
|
+
return descriptorsPaths;
|
|
76
|
+
}, {});
|
|
77
|
+
return {
|
|
78
|
+
paths,
|
|
79
|
+
name,
|
|
80
|
+
keyringAccount,
|
|
81
|
+
xfp: getFingerprintFromSource(source),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
class AirgappedSigner {
|
|
85
|
+
constructor() {
|
|
86
|
+
_AirgappedSigner_instances.add(this);
|
|
87
|
+
_AirgappedSigner_source.set(this, void 0);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Initialize the AirgappedSigner with a source.
|
|
91
|
+
*
|
|
92
|
+
* @param source - The signer source, in the form of details object, or a UR string
|
|
93
|
+
*/
|
|
94
|
+
init(source) {
|
|
95
|
+
if (typeof source === 'string') {
|
|
96
|
+
__classPrivateFieldGet(this, _AirgappedSigner_instances, "m", _AirgappedSigner_initFromUR).call(this, source);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
__classPrivateFieldSet(this, _AirgappedSigner_source, source, "f");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if the AirgappedSigner is initialized
|
|
104
|
+
*
|
|
105
|
+
* @returns True if the AirgappedSigner is initialized, false otherwise
|
|
106
|
+
*/
|
|
107
|
+
isInitialized() {
|
|
108
|
+
return __classPrivateFieldGet(this, _AirgappedSigner_source, "f") !== undefined;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Derive an address from the source at a given index
|
|
112
|
+
*
|
|
113
|
+
* @param index - The index to derive the address from
|
|
114
|
+
* @returns The derived address in hex format
|
|
115
|
+
* @throws Will throw an error if the source is not initialized
|
|
116
|
+
*/
|
|
117
|
+
addressFromIndex(index) {
|
|
118
|
+
if (!__classPrivateFieldGet(this, _AirgappedSigner_source, "f")) {
|
|
119
|
+
throw new Error('UR not initialized');
|
|
120
|
+
}
|
|
121
|
+
if (__classPrivateFieldGet(this, _AirgappedSigner_source, "f").keyringMode === KeyringMode.ACCOUNT) {
|
|
122
|
+
const address = Object.keys(__classPrivateFieldGet(this, _AirgappedSigner_source, "f").paths)[index];
|
|
123
|
+
if (!address) {
|
|
124
|
+
throw new Error(`Address not found for index ${index}`);
|
|
125
|
+
}
|
|
126
|
+
return (0, utils_1.add0x)(address);
|
|
127
|
+
}
|
|
128
|
+
const childPath = `m/${__classPrivateFieldGet(this, _AirgappedSigner_source, "f").childrenPath.replace('*', index.toString())}`;
|
|
129
|
+
const hdKey = hdkey_1.default.fromExtendedKey(__classPrivateFieldGet(this, _AirgappedSigner_source, "f").xpub);
|
|
130
|
+
const childKey = hdKey.derive(childPath);
|
|
131
|
+
const address = Buffer.from((0, util_1.publicToAddress)(childKey.publicKey, true)).toString('hex');
|
|
132
|
+
const normalizedAddress = (0, utils_1.getChecksumAddress)((0, utils_1.add0x)(address));
|
|
133
|
+
__classPrivateFieldGet(this, _AirgappedSigner_source, "f").indexes[normalizedAddress] = index;
|
|
134
|
+
return normalizedAddress;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Retrieve the index of an address from the source
|
|
138
|
+
*
|
|
139
|
+
* @param address - The normalized address to retrieve the index for
|
|
140
|
+
* @returns The index of the address
|
|
141
|
+
*/
|
|
142
|
+
indexFromAddress(address) {
|
|
143
|
+
if (!__classPrivateFieldGet(this, _AirgappedSigner_source, "f")) {
|
|
144
|
+
throw new Error('UR not initialized');
|
|
145
|
+
}
|
|
146
|
+
const cachedIndex = __classPrivateFieldGet(this, _AirgappedSigner_source, "f").indexes[address];
|
|
147
|
+
if (cachedIndex !== undefined) {
|
|
148
|
+
return Number(cachedIndex);
|
|
149
|
+
}
|
|
150
|
+
if (__classPrivateFieldGet(this, _AirgappedSigner_source, "f").keyringMode === KeyringMode.ACCOUNT) {
|
|
151
|
+
const path = __classPrivateFieldGet(this, _AirgappedSigner_source, "f").paths[address];
|
|
152
|
+
if (path === undefined) {
|
|
153
|
+
throw new Error(`Unknown address`);
|
|
154
|
+
}
|
|
155
|
+
const index = path.split('/').pop();
|
|
156
|
+
if (index === undefined) {
|
|
157
|
+
throw new Error(`Invalid path for address ${address}`);
|
|
158
|
+
}
|
|
159
|
+
return Number(index);
|
|
160
|
+
}
|
|
161
|
+
for (let i = 0; i < MAX_INDEX; i++) {
|
|
162
|
+
const derivedAddress = this.addressFromIndex(i);
|
|
163
|
+
if (derivedAddress === address) {
|
|
164
|
+
return i;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
throw new Error(`Address ${address} not found`);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get a page of addresses derived from the source.
|
|
171
|
+
*
|
|
172
|
+
* @param page - The page number to retrieve
|
|
173
|
+
* @param pageSize - The number of addresses per page
|
|
174
|
+
* @returns An array of IndexedAddress objects, each containing the address and its index
|
|
175
|
+
* @throws Will throw an error if the source is not initialized
|
|
176
|
+
*/
|
|
177
|
+
getAddressesPage(page, pageSize = 5) {
|
|
178
|
+
const startIndex = page * pageSize;
|
|
179
|
+
const endIndex = startIndex + pageSize;
|
|
180
|
+
const addresses = [];
|
|
181
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
182
|
+
const address = this.addressFromIndex(i);
|
|
183
|
+
addresses.push({ address, index: i });
|
|
184
|
+
}
|
|
185
|
+
return addresses;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Gets the source details of the AirgappedSigner.
|
|
189
|
+
*
|
|
190
|
+
* @returns The source details, or undefined if not initialized
|
|
191
|
+
*/
|
|
192
|
+
getSourceDetails() {
|
|
193
|
+
return __classPrivateFieldGet(this, _AirgappedSigner_source, "f");
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Clear the source details.
|
|
197
|
+
*/
|
|
198
|
+
clear() {
|
|
199
|
+
__classPrivateFieldSet(this, _AirgappedSigner_source, undefined, "f");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.AirgappedSigner = AirgappedSigner;
|
|
203
|
+
_AirgappedSigner_source = new WeakMap(), _AirgappedSigner_instances = new WeakSet(), _AirgappedSigner_initFromUR = function _AirgappedSigner_initFromUR(ur) {
|
|
204
|
+
const source = __classPrivateFieldGet(this, _AirgappedSigner_instances, "m", _AirgappedSigner_decodeUR).call(this, ur);
|
|
205
|
+
const fingerprint = getFingerprintFromSource(source);
|
|
206
|
+
if (source instanceof bc_ur_registry_eth_1.CryptoAccount) {
|
|
207
|
+
const { name, xfp, paths, keyringAccount } = readCryptoAccountOutputDescriptors(source);
|
|
208
|
+
__classPrivateFieldSet(this, _AirgappedSigner_source, {
|
|
209
|
+
keyringMode: KeyringMode.ACCOUNT,
|
|
210
|
+
keyringAccount,
|
|
211
|
+
name,
|
|
212
|
+
xfp,
|
|
213
|
+
paths,
|
|
214
|
+
indexes: {},
|
|
215
|
+
}, "f");
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
const { getBip32Key, getOrigin, getChildren, getName, getNote } = source;
|
|
219
|
+
__classPrivateFieldSet(this, _AirgappedSigner_source, {
|
|
220
|
+
keyringMode: KeyringMode.HD,
|
|
221
|
+
keyringAccount: getNote(),
|
|
222
|
+
name: getName(),
|
|
223
|
+
xfp: fingerprint,
|
|
224
|
+
hdPath: `m/${getOrigin().getPath()}`,
|
|
225
|
+
childrenPath: getChildren()?.getPath() || DEFAULT_CHILDREN_PATH,
|
|
226
|
+
xpub: getBip32Key(),
|
|
227
|
+
indexes: {},
|
|
228
|
+
}, "f");
|
|
229
|
+
}
|
|
230
|
+
}, _AirgappedSigner_decodeUR = function _AirgappedSigner_decodeUR(ur) {
|
|
231
|
+
const decodedUR = bc_ur_registry_eth_1.URRegistryDecoder.decode(ur);
|
|
232
|
+
const { cbor } = decodedUR;
|
|
233
|
+
switch (decodedUR.type) {
|
|
234
|
+
case exports.SUPPORTED_UR_TYPE.CRYPTO_HDKEY:
|
|
235
|
+
return bc_ur_registry_eth_1.CryptoHDKey.fromCBOR(cbor);
|
|
236
|
+
case exports.SUPPORTED_UR_TYPE.CRYPTO_ACCOUNT:
|
|
237
|
+
return bc_ur_registry_eth_1.CryptoAccount.fromCBOR(cbor);
|
|
238
|
+
default:
|
|
239
|
+
throw new Error('Unsupported UR type');
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=airgapped-signer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airgapped-signer.cjs","sourceRoot":"","sources":["../src/airgapped-signer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,2CAAmD;AACnD,uEAIwC;AACxC,2CAAsE;AACtE,gEAAgE;AAChE,kDAA0B;AAEb,QAAA,iBAAiB,GAAG;IAC/B,YAAY,EAAE,cAAc;IAC5B,cAAc,EAAE,gBAAgB;IAChC,aAAa,EAAE,eAAe;CAC/B,CAAC;AAEF,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,wBAAS,CAAA;IACT,kCAAmB,CAAA;AACrB,CAAC,EAHW,WAAW,2BAAX,WAAW,QAGtB;AAED,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAK,CAAC;AAgFxB;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,MAAmC;IACnE,OAAO,MAAM,YAAY,kCAAa;QACpC,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC;QAChD,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,kCAAkC,CAAC,MAAqB;IAM/D,MAAM,WAAW,GAAG,MAAM,CAAC,oBAAoB,EAAE,CAAC;IAElD,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,cAAc,GAAG,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAC9B,CAAC,gBAAqC,EAAE,OAAO,EAAE,EAAE;QACjD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,OAAO,GAAG,IAAA,0BAAkB,EAChC,IAAA,aAAK,EACH,MAAM,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CACnE,CACF,CAAC;YACF,gBAAgB,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;YACjC,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;YACvB,cAAc,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,gBAAgB,CAAC;IAC1B,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO;QACL,KAAK;QACL,IAAI;QACJ,cAAc;QACd,GAAG,EAAE,wBAAwB,CAAC,MAAM,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAa,eAAe;IAA5B;;QACE,0CAA6C;IAmM/C,CAAC;IAjMC;;;;OAIG;IACH,IAAI,CAAC,MAAuC;QAC1C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,uBAAA,IAAI,+DAAY,MAAhB,IAAI,EAAa,MAAM,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,uBAAA,IAAI,2BAAW,MAAM,MAAA,CAAC;QACxB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,aAAa;QACX,OAAO,uBAAA,IAAI,+BAAQ,KAAK,SAAS,CAAC;IACpC,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAa;QAC5B,IAAI,CAAC,uBAAA,IAAI,+BAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,uBAAA,IAAI,+BAAQ,CAAC,WAAW,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC;YACrD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAA,IAAI,+BAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;YACvD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,IAAA,aAAK,EAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,MAAM,SAAS,GAAG,KAAK,uBAAA,IAAI,+BAAQ,CAAC,YAAY,CAAC,OAAO,CACtD,GAAG,EACH,KAAK,CAAC,QAAQ,EAAE,CACjB,EAAE,CAAC;QAEJ,MAAM,KAAK,GAAG,eAAK,CAAC,eAAe,CAAC,uBAAA,IAAI,+BAAQ,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CACzB,IAAA,sBAAe,EAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAC1C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAElB,MAAM,iBAAiB,GAAG,IAAA,0BAAkB,EAAC,IAAA,aAAK,EAAC,OAAO,CAAC,CAAC,CAAC;QAE7D,uBAAA,IAAI,+BAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,KAAK,CAAC;QAEhD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,OAAY;QAC3B,IAAI,CAAC,uBAAA,IAAI,+BAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,MAAM,WAAW,GAAG,uBAAA,IAAI,+BAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,uBAAA,IAAI,+BAAQ,CAAC,WAAW,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC;YACrD,MAAM,IAAI,GAAG,uBAAA,IAAI,+BAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAChD,IAAI,cAAc,KAAK,OAAO,EAAE,CAAC;gBAC/B,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,YAAY,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAY,EAAE,QAAQ,GAAG,CAAC;QACzC,MAAM,UAAU,GAAG,IAAI,GAAG,QAAQ,CAAC;QACnC,MAAM,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;QACvC,MAAM,SAAS,GAAqB,EAAE,CAAC;QAEvC,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YACzC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACd,OAAO,uBAAA,IAAI,+BAAQ,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,uBAAA,IAAI,2BAAW,SAAS,MAAA,CAAC;IAC3B,CAAC;CA0DF;AApMD,0CAoMC;wJAnDa,EAAU;IACpB,MAAM,MAAM,GAAG,uBAAA,IAAI,6DAAU,MAAd,IAAI,EAAW,EAAE,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAErD,IAAI,MAAM,YAAY,kCAAa,EAAE,CAAC;QACpC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,GACxC,kCAAkC,CAAC,MAAM,CAAC,CAAC;QAC7C,uBAAA,IAAI,2BAAW;YACb,WAAW,EAAE,WAAW,CAAC,OAAO;YAChC,cAAc;YACd,IAAI;YACJ,GAAG;YACH,KAAK;YACL,OAAO,EAAE,EAAE;SACZ,MAAA,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QACzE,uBAAA,IAAI,2BAAW;YACb,WAAW,EAAE,WAAW,CAAC,EAAE;YAC3B,cAAc,EAAE,OAAO,EAAE;YACzB,IAAI,EAAE,OAAO,EAAE;YACf,GAAG,EAAE,WAAW;YAChB,MAAM,EAAE,KAAK,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACpC,YAAY,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,qBAAqB;YAC/D,IAAI,EAAE,WAAW,EAAE;YACnB,OAAO,EAAE,EAAE;SACZ,MAAA,CAAC;IACJ,CAAC;AACH,CAAC,iEASS,EAAU;IAClB,MAAM,SAAS,GAAG,sCAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAE/C,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;IAE3B,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,yBAAiB,CAAC,YAAY;YACjC,OAAO,gCAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,KAAK,yBAAiB,CAAC,cAAc;YACnC,OAAO,kCAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC","sourcesContent":["import { publicToAddress } from '@ethereumjs/util';\nimport {\n CryptoAccount,\n CryptoHDKey,\n URRegistryDecoder,\n} from '@keystonehq/bc-ur-registry-eth';\nimport { add0x, getChecksumAddress, type Hex } from '@metamask/utils';\n// eslint-disable-next-line @typescript-eslint/naming-convention\nimport HdKey from 'hdkey';\n\nexport const SUPPORTED_UR_TYPE = {\n CRYPTO_HDKEY: 'crypto-hdkey',\n CRYPTO_ACCOUNT: 'crypto-account',\n ETH_SIGNATURE: 'eth-signature',\n};\n\nexport enum KeyringMode {\n HD = 'hd',\n ACCOUNT = 'account',\n}\n\nconst DEFAULT_CHILDREN_PATH = '0/*';\n\nconst MAX_INDEX = 1_000;\n\n/**\n * Common details for the signer source, which can be either a CryptoAccount or CryptoHDKey.\n */\nexport type CommonSignerDetails = {\n /**\n * Value take out from the device note field, if available.\n */\n keyringAccount: string;\n /**\n * The name of the device\n */\n name: string;\n /**\n * The device fingerprint, hex-encoded\n */\n xfp: string;\n /**\n * Indexes of the accounts derived from the device\n * in the form of a map from address to index\n */\n indexes: Record<Hex, number>;\n};\n\n/**\n * Details for the HD mode of the AirgappedSigner. This mode derives\n * accounts from a root public key (xpub) and a derivation path.\n */\nexport type HDModeSignerDetails = {\n /**\n * The keyring mode is HD, indicating that it derives accounts from a\n * root public key (xpub) and a derivation path.\n */\n keyringMode: KeyringMode.HD;\n /**\n * The xpub of the HD key\n */\n xpub: string;\n /**\n * The derivation path of the HD key\n */\n hdPath: string;\n /**\n * The path used to derive child accounts\n */\n childrenPath: string;\n};\n\n/**\n * Details for the Account mode of the AirgappedSigner. This mode derives\n * accounts from a set of addresses and their corresponding paths.\n */\nexport type AccountModeSignerDetails = {\n /**\n * The keyring mode is ACCOUNT, indicating that it derives accounts from\n * a set of addresses and their corresponding paths.\n */\n keyringMode: KeyringMode.ACCOUNT;\n /**\n * The derivation paths for each hex-encoded address in the device\n */\n paths: Record<Hex, string>;\n};\n\n/**\n * An address with its corresponding index.\n */\nexport type IndexedAddress = {\n address: Hex;\n index: number;\n};\n\n/**\n * The details of the source CryptoAccount or CryptoHDKey\n * that the AirgappedSigner uses to derive accounts.\n */\nexport type AirgappedSignerDetails = CommonSignerDetails &\n (HDModeSignerDetails | AccountModeSignerDetails);\n\n/**\n * Get the fingerprint of the source CryptoAccount or CryptoHDKey\n *\n * @param source - The source CryptoAccount or CryptoHDKey\n * @returns The fingerprint of the source\n */\nfunction getFingerprintFromSource(source: CryptoAccount | CryptoHDKey): string {\n return source instanceof CryptoAccount\n ? source.getMasterFingerprint()?.toString('hex')\n : source.getParentFingerprint()?.toString('hex');\n}\n\n/**\n * Get fingerprint, account paths and names from the a CryptoAccount\n *\n * Note: This function emulates the behavior of the `@keystonehq/base-eth-keyring`\n * library when dealing with CryptoAccount objects (for backwards compatibility\n * reasons). Though, the way it retrieves `name` and `keyringAccount` is questionable,\n * as `name` and `keyringAccount` are updated after each descriptor discovery, effectively\n * returning the last descriptor's `name` and `keyringAccount`.\n *\n * @param source - The source CryptoAccount\n * @returns The paths\n */\nfunction readCryptoAccountOutputDescriptors(source: CryptoAccount): {\n xfp: string;\n paths: Record<Hex, string>;\n name: string;\n keyringAccount: string;\n} {\n const descriptors = source.getOutputDescriptors();\n\n if (!descriptors || descriptors.length === 0) {\n throw new Error('No output descriptors found in CryptoAccount');\n }\n\n let name = '';\n let keyringAccount = '';\n const paths = descriptors.reduce(\n (descriptorsPaths: Record<Hex, string>, current) => {\n const hdKey = current.getHDKey();\n if (hdKey) {\n const path = `M/${hdKey.getOrigin().getPath()}`;\n const address = getChecksumAddress(\n add0x(\n Buffer.from(publicToAddress(hdKey.getKey(), true)).toString('hex'),\n ),\n );\n descriptorsPaths[address] = path;\n name = hdKey.getName();\n keyringAccount = hdKey.getNote();\n }\n return descriptorsPaths;\n },\n {},\n );\n\n return {\n paths,\n name,\n keyringAccount,\n xfp: getFingerprintFromSource(source),\n };\n}\n\nexport class AirgappedSigner {\n #source?: AirgappedSignerDetails | undefined;\n\n /**\n * Initialize the AirgappedSigner with a source.\n *\n * @param source - The signer source, in the form of details object, or a UR string\n */\n init(source: AirgappedSignerDetails | string): void {\n if (typeof source === 'string') {\n this.#initFromUR(source);\n } else {\n this.#source = source;\n }\n }\n\n /**\n * Check if the AirgappedSigner is initialized\n *\n * @returns True if the AirgappedSigner is initialized, false otherwise\n */\n isInitialized(): boolean {\n return this.#source !== undefined;\n }\n\n /**\n * Derive an address from the source at a given index\n *\n * @param index - The index to derive the address from\n * @returns The derived address in hex format\n * @throws Will throw an error if the source is not initialized\n */\n addressFromIndex(index: number): Hex {\n if (!this.#source) {\n throw new Error('UR not initialized');\n }\n\n if (this.#source.keyringMode === KeyringMode.ACCOUNT) {\n const address = Object.keys(this.#source.paths)[index];\n if (!address) {\n throw new Error(`Address not found for index ${index}`);\n }\n return add0x(address);\n }\n const childPath = `m/${this.#source.childrenPath.replace(\n '*',\n index.toString(),\n )}`;\n\n const hdKey = HdKey.fromExtendedKey(this.#source.xpub);\n const childKey = hdKey.derive(childPath);\n\n const address = Buffer.from(\n publicToAddress(childKey.publicKey, true),\n ).toString('hex');\n\n const normalizedAddress = getChecksumAddress(add0x(address));\n\n this.#source.indexes[normalizedAddress] = index;\n\n return normalizedAddress;\n }\n\n /**\n * Retrieve the index of an address from the source\n *\n * @param address - The normalized address to retrieve the index for\n * @returns The index of the address\n */\n indexFromAddress(address: Hex): number {\n if (!this.#source) {\n throw new Error('UR not initialized');\n }\n\n const cachedIndex = this.#source.indexes[address];\n if (cachedIndex !== undefined) {\n return Number(cachedIndex);\n }\n\n if (this.#source.keyringMode === KeyringMode.ACCOUNT) {\n const path = this.#source.paths[address];\n if (path === undefined) {\n throw new Error(`Unknown address`);\n }\n\n const index = path.split('/').pop();\n if (index === undefined) {\n throw new Error(`Invalid path for address ${address}`);\n }\n\n return Number(index);\n }\n\n for (let i = 0; i < MAX_INDEX; i++) {\n const derivedAddress = this.addressFromIndex(i);\n if (derivedAddress === address) {\n return i;\n }\n }\n\n throw new Error(`Address ${address} not found`);\n }\n\n /**\n * Get a page of addresses derived from the source.\n *\n * @param page - The page number to retrieve\n * @param pageSize - The number of addresses per page\n * @returns An array of IndexedAddress objects, each containing the address and its index\n * @throws Will throw an error if the source is not initialized\n */\n getAddressesPage(page: number, pageSize = 5): IndexedAddress[] {\n const startIndex = page * pageSize;\n const endIndex = startIndex + pageSize;\n const addresses: IndexedAddress[] = [];\n\n for (let i = startIndex; i < endIndex; i++) {\n const address = this.addressFromIndex(i);\n addresses.push({ address, index: i });\n }\n\n return addresses;\n }\n\n /**\n * Gets the source details of the AirgappedSigner.\n *\n * @returns The source details, or undefined if not initialized\n */\n getSourceDetails(): AirgappedSignerDetails | undefined {\n return this.#source;\n }\n\n /**\n * Clear the source details.\n */\n clear(): void {\n this.#source = undefined;\n }\n\n /**\n * Set the root account from a UR string\n *\n * @param ur - The UR string to set the root account from\n */\n #initFromUR(ur: string): void {\n const source = this.#decodeUR(ur);\n const fingerprint = getFingerprintFromSource(source);\n\n if (source instanceof CryptoAccount) {\n const { name, xfp, paths, keyringAccount } =\n readCryptoAccountOutputDescriptors(source);\n this.#source = {\n keyringMode: KeyringMode.ACCOUNT,\n keyringAccount,\n name,\n xfp,\n paths,\n indexes: {},\n };\n } else {\n const { getBip32Key, getOrigin, getChildren, getName, getNote } = source;\n this.#source = {\n keyringMode: KeyringMode.HD,\n keyringAccount: getNote(),\n name: getName(),\n xfp: fingerprint,\n hdPath: `m/${getOrigin().getPath()}`,\n childrenPath: getChildren()?.getPath() || DEFAULT_CHILDREN_PATH,\n xpub: getBip32Key(),\n indexes: {},\n };\n }\n }\n\n /**\n * Decodes a UR\n *\n * @param ur - The UR to decode\n * @returns The decoded CryptoAccount or CryptoHDKey\n * @throws Will throw an error if the UR type is not supported\n */\n #decodeUR(ur: string): CryptoAccount | CryptoHDKey {\n const decodedUR = URRegistryDecoder.decode(ur);\n\n const { cbor } = decodedUR;\n\n switch (decodedUR.type) {\n case SUPPORTED_UR_TYPE.CRYPTO_HDKEY:\n return CryptoHDKey.fromCBOR(cbor);\n case SUPPORTED_UR_TYPE.CRYPTO_ACCOUNT:\n return CryptoAccount.fromCBOR(cbor);\n default:\n throw new Error('Unsupported UR type');\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type Hex } from "@metamask/utils";
|
|
2
|
+
export declare const SUPPORTED_UR_TYPE: {
|
|
3
|
+
CRYPTO_HDKEY: string;
|
|
4
|
+
CRYPTO_ACCOUNT: string;
|
|
5
|
+
ETH_SIGNATURE: string;
|
|
6
|
+
};
|
|
7
|
+
export declare enum KeyringMode {
|
|
8
|
+
HD = "hd",
|
|
9
|
+
ACCOUNT = "account"
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Common details for the signer source, which can be either a CryptoAccount or CryptoHDKey.
|
|
13
|
+
*/
|
|
14
|
+
export type CommonSignerDetails = {
|
|
15
|
+
/**
|
|
16
|
+
* Value take out from the device note field, if available.
|
|
17
|
+
*/
|
|
18
|
+
keyringAccount: string;
|
|
19
|
+
/**
|
|
20
|
+
* The name of the device
|
|
21
|
+
*/
|
|
22
|
+
name: string;
|
|
23
|
+
/**
|
|
24
|
+
* The device fingerprint, hex-encoded
|
|
25
|
+
*/
|
|
26
|
+
xfp: string;
|
|
27
|
+
/**
|
|
28
|
+
* Indexes of the accounts derived from the device
|
|
29
|
+
* in the form of a map from address to index
|
|
30
|
+
*/
|
|
31
|
+
indexes: Record<Hex, number>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Details for the HD mode of the AirgappedSigner. This mode derives
|
|
35
|
+
* accounts from a root public key (xpub) and a derivation path.
|
|
36
|
+
*/
|
|
37
|
+
export type HDModeSignerDetails = {
|
|
38
|
+
/**
|
|
39
|
+
* The keyring mode is HD, indicating that it derives accounts from a
|
|
40
|
+
* root public key (xpub) and a derivation path.
|
|
41
|
+
*/
|
|
42
|
+
keyringMode: KeyringMode.HD;
|
|
43
|
+
/**
|
|
44
|
+
* The xpub of the HD key
|
|
45
|
+
*/
|
|
46
|
+
xpub: string;
|
|
47
|
+
/**
|
|
48
|
+
* The derivation path of the HD key
|
|
49
|
+
*/
|
|
50
|
+
hdPath: string;
|
|
51
|
+
/**
|
|
52
|
+
* The path used to derive child accounts
|
|
53
|
+
*/
|
|
54
|
+
childrenPath: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Details for the Account mode of the AirgappedSigner. This mode derives
|
|
58
|
+
* accounts from a set of addresses and their corresponding paths.
|
|
59
|
+
*/
|
|
60
|
+
export type AccountModeSignerDetails = {
|
|
61
|
+
/**
|
|
62
|
+
* The keyring mode is ACCOUNT, indicating that it derives accounts from
|
|
63
|
+
* a set of addresses and their corresponding paths.
|
|
64
|
+
*/
|
|
65
|
+
keyringMode: KeyringMode.ACCOUNT;
|
|
66
|
+
/**
|
|
67
|
+
* The derivation paths for each hex-encoded address in the device
|
|
68
|
+
*/
|
|
69
|
+
paths: Record<Hex, string>;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* An address with its corresponding index.
|
|
73
|
+
*/
|
|
74
|
+
export type IndexedAddress = {
|
|
75
|
+
address: Hex;
|
|
76
|
+
index: number;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The details of the source CryptoAccount or CryptoHDKey
|
|
80
|
+
* that the AirgappedSigner uses to derive accounts.
|
|
81
|
+
*/
|
|
82
|
+
export type AirgappedSignerDetails = CommonSignerDetails & (HDModeSignerDetails | AccountModeSignerDetails);
|
|
83
|
+
export declare class AirgappedSigner {
|
|
84
|
+
#private;
|
|
85
|
+
/**
|
|
86
|
+
* Initialize the AirgappedSigner with a source.
|
|
87
|
+
*
|
|
88
|
+
* @param source - The signer source, in the form of details object, or a UR string
|
|
89
|
+
*/
|
|
90
|
+
init(source: AirgappedSignerDetails | string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Check if the AirgappedSigner is initialized
|
|
93
|
+
*
|
|
94
|
+
* @returns True if the AirgappedSigner is initialized, false otherwise
|
|
95
|
+
*/
|
|
96
|
+
isInitialized(): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Derive an address from the source at a given index
|
|
99
|
+
*
|
|
100
|
+
* @param index - The index to derive the address from
|
|
101
|
+
* @returns The derived address in hex format
|
|
102
|
+
* @throws Will throw an error if the source is not initialized
|
|
103
|
+
*/
|
|
104
|
+
addressFromIndex(index: number): Hex;
|
|
105
|
+
/**
|
|
106
|
+
* Retrieve the index of an address from the source
|
|
107
|
+
*
|
|
108
|
+
* @param address - The normalized address to retrieve the index for
|
|
109
|
+
* @returns The index of the address
|
|
110
|
+
*/
|
|
111
|
+
indexFromAddress(address: Hex): number;
|
|
112
|
+
/**
|
|
113
|
+
* Get a page of addresses derived from the source.
|
|
114
|
+
*
|
|
115
|
+
* @param page - The page number to retrieve
|
|
116
|
+
* @param pageSize - The number of addresses per page
|
|
117
|
+
* @returns An array of IndexedAddress objects, each containing the address and its index
|
|
118
|
+
* @throws Will throw an error if the source is not initialized
|
|
119
|
+
*/
|
|
120
|
+
getAddressesPage(page: number, pageSize?: number): IndexedAddress[];
|
|
121
|
+
/**
|
|
122
|
+
* Gets the source details of the AirgappedSigner.
|
|
123
|
+
*
|
|
124
|
+
* @returns The source details, or undefined if not initialized
|
|
125
|
+
*/
|
|
126
|
+
getSourceDetails(): AirgappedSignerDetails | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Clear the source details.
|
|
129
|
+
*/
|
|
130
|
+
clear(): void;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=airgapped-signer.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airgapped-signer.d.cts","sourceRoot":"","sources":["../src/airgapped-signer.ts"],"names":[],"mappings":"AAMA,OAAO,EAA6B,KAAK,GAAG,EAAE,wBAAwB;AAItE,eAAO,MAAM,iBAAiB;;;;CAI7B,CAAC;AAEF,oBAAY,WAAW;IACrB,EAAE,OAAO;IACT,OAAO,YAAY;CACpB;AAMD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,GAAG,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,GACtD,CAAC,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;AAmEnD,qBAAa,eAAe;;IAG1B;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAQnD;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IA+BpC;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM;IAkCtC;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,cAAc,EAAE;IAa9D;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,GAAG,SAAS;IAItD;;OAEG;IACH,KAAK,IAAI,IAAI;CA4Dd"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type Hex } from "@metamask/utils";
|
|
2
|
+
export declare const SUPPORTED_UR_TYPE: {
|
|
3
|
+
CRYPTO_HDKEY: string;
|
|
4
|
+
CRYPTO_ACCOUNT: string;
|
|
5
|
+
ETH_SIGNATURE: string;
|
|
6
|
+
};
|
|
7
|
+
export declare enum KeyringMode {
|
|
8
|
+
HD = "hd",
|
|
9
|
+
ACCOUNT = "account"
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Common details for the signer source, which can be either a CryptoAccount or CryptoHDKey.
|
|
13
|
+
*/
|
|
14
|
+
export type CommonSignerDetails = {
|
|
15
|
+
/**
|
|
16
|
+
* Value take out from the device note field, if available.
|
|
17
|
+
*/
|
|
18
|
+
keyringAccount: string;
|
|
19
|
+
/**
|
|
20
|
+
* The name of the device
|
|
21
|
+
*/
|
|
22
|
+
name: string;
|
|
23
|
+
/**
|
|
24
|
+
* The device fingerprint, hex-encoded
|
|
25
|
+
*/
|
|
26
|
+
xfp: string;
|
|
27
|
+
/**
|
|
28
|
+
* Indexes of the accounts derived from the device
|
|
29
|
+
* in the form of a map from address to index
|
|
30
|
+
*/
|
|
31
|
+
indexes: Record<Hex, number>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Details for the HD mode of the AirgappedSigner. This mode derives
|
|
35
|
+
* accounts from a root public key (xpub) and a derivation path.
|
|
36
|
+
*/
|
|
37
|
+
export type HDModeSignerDetails = {
|
|
38
|
+
/**
|
|
39
|
+
* The keyring mode is HD, indicating that it derives accounts from a
|
|
40
|
+
* root public key (xpub) and a derivation path.
|
|
41
|
+
*/
|
|
42
|
+
keyringMode: KeyringMode.HD;
|
|
43
|
+
/**
|
|
44
|
+
* The xpub of the HD key
|
|
45
|
+
*/
|
|
46
|
+
xpub: string;
|
|
47
|
+
/**
|
|
48
|
+
* The derivation path of the HD key
|
|
49
|
+
*/
|
|
50
|
+
hdPath: string;
|
|
51
|
+
/**
|
|
52
|
+
* The path used to derive child accounts
|
|
53
|
+
*/
|
|
54
|
+
childrenPath: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Details for the Account mode of the AirgappedSigner. This mode derives
|
|
58
|
+
* accounts from a set of addresses and their corresponding paths.
|
|
59
|
+
*/
|
|
60
|
+
export type AccountModeSignerDetails = {
|
|
61
|
+
/**
|
|
62
|
+
* The keyring mode is ACCOUNT, indicating that it derives accounts from
|
|
63
|
+
* a set of addresses and their corresponding paths.
|
|
64
|
+
*/
|
|
65
|
+
keyringMode: KeyringMode.ACCOUNT;
|
|
66
|
+
/**
|
|
67
|
+
* The derivation paths for each hex-encoded address in the device
|
|
68
|
+
*/
|
|
69
|
+
paths: Record<Hex, string>;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* An address with its corresponding index.
|
|
73
|
+
*/
|
|
74
|
+
export type IndexedAddress = {
|
|
75
|
+
address: Hex;
|
|
76
|
+
index: number;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The details of the source CryptoAccount or CryptoHDKey
|
|
80
|
+
* that the AirgappedSigner uses to derive accounts.
|
|
81
|
+
*/
|
|
82
|
+
export type AirgappedSignerDetails = CommonSignerDetails & (HDModeSignerDetails | AccountModeSignerDetails);
|
|
83
|
+
export declare class AirgappedSigner {
|
|
84
|
+
#private;
|
|
85
|
+
/**
|
|
86
|
+
* Initialize the AirgappedSigner with a source.
|
|
87
|
+
*
|
|
88
|
+
* @param source - The signer source, in the form of details object, or a UR string
|
|
89
|
+
*/
|
|
90
|
+
init(source: AirgappedSignerDetails | string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Check if the AirgappedSigner is initialized
|
|
93
|
+
*
|
|
94
|
+
* @returns True if the AirgappedSigner is initialized, false otherwise
|
|
95
|
+
*/
|
|
96
|
+
isInitialized(): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Derive an address from the source at a given index
|
|
99
|
+
*
|
|
100
|
+
* @param index - The index to derive the address from
|
|
101
|
+
* @returns The derived address in hex format
|
|
102
|
+
* @throws Will throw an error if the source is not initialized
|
|
103
|
+
*/
|
|
104
|
+
addressFromIndex(index: number): Hex;
|
|
105
|
+
/**
|
|
106
|
+
* Retrieve the index of an address from the source
|
|
107
|
+
*
|
|
108
|
+
* @param address - The normalized address to retrieve the index for
|
|
109
|
+
* @returns The index of the address
|
|
110
|
+
*/
|
|
111
|
+
indexFromAddress(address: Hex): number;
|
|
112
|
+
/**
|
|
113
|
+
* Get a page of addresses derived from the source.
|
|
114
|
+
*
|
|
115
|
+
* @param page - The page number to retrieve
|
|
116
|
+
* @param pageSize - The number of addresses per page
|
|
117
|
+
* @returns An array of IndexedAddress objects, each containing the address and its index
|
|
118
|
+
* @throws Will throw an error if the source is not initialized
|
|
119
|
+
*/
|
|
120
|
+
getAddressesPage(page: number, pageSize?: number): IndexedAddress[];
|
|
121
|
+
/**
|
|
122
|
+
* Gets the source details of the AirgappedSigner.
|
|
123
|
+
*
|
|
124
|
+
* @returns The source details, or undefined if not initialized
|
|
125
|
+
*/
|
|
126
|
+
getSourceDetails(): AirgappedSignerDetails | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Clear the source details.
|
|
129
|
+
*/
|
|
130
|
+
clear(): void;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=airgapped-signer.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airgapped-signer.d.mts","sourceRoot":"","sources":["../src/airgapped-signer.ts"],"names":[],"mappings":"AAMA,OAAO,EAA6B,KAAK,GAAG,EAAE,wBAAwB;AAItE,eAAO,MAAM,iBAAiB;;;;CAI7B,CAAC;AAEF,oBAAY,WAAW;IACrB,EAAE,OAAO;IACT,OAAO,YAAY;CACpB;AAMD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,GAAG,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,GACtD,CAAC,mBAAmB,GAAG,wBAAwB,CAAC,CAAC;AAmEnD,qBAAa,eAAe;;IAG1B;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI;IAQnD;;;;OAIG;IACH,aAAa,IAAI,OAAO;IAIxB;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IA+BpC;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM;IAkCtC;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,cAAc,EAAE;IAa9D;;;;OAIG;IACH,gBAAgB,IAAI,sBAAsB,GAAG,SAAS;IAItD;;OAEG;IACH,KAAK,IAAI,IAAI;CA4Dd"}
|