mirror of
https://github.com/pezkuwichain/pezkuwi-common.git
synced 2026-04-21 23:48:05 +00:00
chore: update to version 14.0.11 and align website URLs
This commit is contained in:
+2
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,5 @@
|
||||
import LedgerHid from '@ledgerhq/hw-transport-webhid';
|
||||
import LedgerUsb from '@ledgerhq/hw-transport-webusb';
|
||||
import { createDefs } from './util.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export const transports = /*#__PURE__*/ createDefs(['webusb', LedgerUsb], ['hid', LedgerHid]);
|
||||
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transports = exports.packageInfo = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const hw_transport_webhid_1 = tslib_1.__importDefault(require("@ledgerhq/hw-transport-webhid"));
|
||||
const hw_transport_webusb_1 = tslib_1.__importDefault(require("@ledgerhq/hw-transport-webusb"));
|
||||
const util_js_1 = require("./util.js");
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
exports.transports = (0, util_js_1.createDefs)(['webusb', hw_transport_webusb_1.default], ['hid', hw_transport_webhid_1.default]);
|
||||
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transports = exports.packageInfo = void 0;
|
||||
const util_js_1 = require("./util.js");
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
exports.transports = (0, util_js_1.createDefs)();
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transports = exports.packageInfo = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const hw_transport_node_hid_singleton_1 = tslib_1.__importDefault(require("@ledgerhq/hw-transport-node-hid-singleton"));
|
||||
const util_js_1 = require("./util.js");
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
exports.transports = (0, util_js_1.createDefs)(['hid', hw_transport_node_hid_singleton_1.default]);
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const packageInfo_js_1 = require("./packageInfo.js");
|
||||
(0, util_1.detectPackage)(packageInfo_js_1.packageInfo, null, []);
|
||||
@@ -0,0 +1,6 @@
|
||||
export declare const packageInfo: {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
version: string;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.packageInfo = void 0;
|
||||
exports.packageInfo = { name: '@pezkuwi/hw-ledger-transports', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '14.0.10' };
|
||||
@@ -0,0 +1 @@
|
||||
export * from './empty.js';
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./empty.js"), exports);
|
||||
@@ -0,0 +1,9 @@
|
||||
import type * as HwTransport from '@ledgerhq/hw-transport';
|
||||
export type TransportType = 'hid' | 'webusb';
|
||||
export type Transport = HwTransport.default;
|
||||
export interface TransportDef {
|
||||
/** Create a transport to be used in Ledger operations */
|
||||
create(): Promise<Transport>;
|
||||
/** The type of the underlying transport definition */
|
||||
type: TransportType;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { TransportDef, TransportType } from './types.js';
|
||||
export declare function createDefs(...items: readonly [type: TransportType, Clazz: unknown][]): TransportDef[];
|
||||
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDefs = createDefs;
|
||||
function createDefs(...items) {
|
||||
return items.map(([type, Clazz]) => ({
|
||||
create: () => Clazz.create(),
|
||||
type
|
||||
}));
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,3 @@
|
||||
import { createDefs } from './util.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export const transports = /*#__PURE__*/ createDefs();
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export declare const transports: import("./types.js").TransportDef[];
|
||||
@@ -0,0 +1,4 @@
|
||||
import LedgerHid from '@ledgerhq/hw-transport-node-hid-singleton';
|
||||
import { createDefs } from './util.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export const transports = /*#__PURE__*/ createDefs(['hid', LedgerHid]);
|
||||
@@ -14,15 +14,196 @@
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "14.0.10",
|
||||
"browser": "browser.js",
|
||||
"main": "node.js",
|
||||
"react-native": "react-native.js",
|
||||
"version": "14.0.11",
|
||||
"main": "./cjs/node.js",
|
||||
"module": "./node.js",
|
||||
"browser": "./cjs/browser.js",
|
||||
"react-native": "./cjs/react-native.js",
|
||||
"types": "./node.d.ts",
|
||||
"exports": {
|
||||
"./cjs/package.json": "./cjs/package.json",
|
||||
"./cjs/*": "./cjs/*.js",
|
||||
".": {
|
||||
"types": "./node.d.ts",
|
||||
"react-native": {
|
||||
"module": {
|
||||
"types": "./react-native.d.ts",
|
||||
"default": "./react-native.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/react-native.d.ts",
|
||||
"default": "./cjs/react-native.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./react-native.d.ts",
|
||||
"default": "./react-native.js"
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"module": {
|
||||
"types": "./browser.d.ts",
|
||||
"default": "./browser.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/browser.d.ts",
|
||||
"default": "./cjs/browser.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./browser.d.ts",
|
||||
"default": "./browser.js"
|
||||
}
|
||||
},
|
||||
"node": {
|
||||
"module": {
|
||||
"types": "./node.d.ts",
|
||||
"default": "./node.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/node.d.ts",
|
||||
"default": "./cjs/node.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./node.d.ts",
|
||||
"default": "./node.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"./browser": {
|
||||
"module": {
|
||||
"types": "./browser.d.ts",
|
||||
"default": "./browser.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/browser.d.ts",
|
||||
"default": "./cjs/browser.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./browser.d.ts",
|
||||
"default": "./browser.js"
|
||||
}
|
||||
},
|
||||
"./empty": {
|
||||
"module": {
|
||||
"types": "./empty.d.ts",
|
||||
"default": "./empty.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/empty.d.ts",
|
||||
"default": "./cjs/empty.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./empty.d.ts",
|
||||
"default": "./empty.js"
|
||||
}
|
||||
},
|
||||
"./node": {
|
||||
"module": {
|
||||
"types": "./node.d.ts",
|
||||
"default": "./node.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/node.d.ts",
|
||||
"default": "./cjs/node.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./node.d.ts",
|
||||
"default": "./node.js"
|
||||
}
|
||||
},
|
||||
"./package.json": {
|
||||
"require": "./cjs/package.json",
|
||||
"default": "./package.json"
|
||||
},
|
||||
"./packageDetect": {
|
||||
"module": {
|
||||
"types": "./packageDetect.d.ts",
|
||||
"default": "./packageDetect.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageDetect.d.ts",
|
||||
"default": "./cjs/packageDetect.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageDetect.d.ts",
|
||||
"default": "./packageDetect.js"
|
||||
}
|
||||
},
|
||||
"./packageInfo.js": {
|
||||
"module": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageInfo.d.ts",
|
||||
"default": "./cjs/packageInfo.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
}
|
||||
},
|
||||
"./packageInfo": {
|
||||
"module": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageInfo.d.ts",
|
||||
"default": "./cjs/packageInfo.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
}
|
||||
},
|
||||
"./react-native": {
|
||||
"module": {
|
||||
"types": "./react-native.d.ts",
|
||||
"default": "./react-native.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/react-native.d.ts",
|
||||
"default": "./cjs/react-native.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./react-native.d.ts",
|
||||
"default": "./react-native.js"
|
||||
}
|
||||
},
|
||||
"./types": {
|
||||
"module": {
|
||||
"types": "./types.d.ts",
|
||||
"default": "./types.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/types.d.ts",
|
||||
"default": "./cjs/types.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./types.d.ts",
|
||||
"default": "./types.js"
|
||||
}
|
||||
},
|
||||
"./util": {
|
||||
"module": {
|
||||
"types": "./util.d.ts",
|
||||
"default": "./util.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/util.d.ts",
|
||||
"default": "./cjs/util.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./util.d.ts",
|
||||
"default": "./util.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@ledgerhq/hw-transport": "^6.31.4",
|
||||
"@ledgerhq/hw-transport-webhid": "^6.29.4",
|
||||
"@ledgerhq/hw-transport-webusb": "^6.29.4",
|
||||
"@pezkuwi/util": "workspace:*",
|
||||
"@pezkuwi/util": "14.0.11",
|
||||
"tslib": "^2.8.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,3 @@
|
||||
import { detectPackage } from '@pezkuwi/util';
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
detectPackage(packageInfo, null, []);
|
||||
@@ -0,0 +1,6 @@
|
||||
export declare const packageInfo: {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
version: string;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export const packageInfo = { name: '@pezkuwi/hw-ledger-transports', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '14.0.10' };
|
||||
@@ -0,0 +1 @@
|
||||
export * from './empty.js';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './empty.js';
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import type * as HwTransport from '@ledgerhq/hw-transport';
|
||||
export type TransportType = 'hid' | 'webusb';
|
||||
export type Transport = HwTransport.default;
|
||||
export interface TransportDef {
|
||||
/** Create a transport to be used in Ledger operations */
|
||||
create(): Promise<Transport>;
|
||||
/** The type of the underlying transport definition */
|
||||
type: TransportType;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { TransportDef, TransportType } from './types.js';
|
||||
export declare function createDefs(...items: readonly [type: TransportType, Clazz: unknown][]): TransportDef[];
|
||||
@@ -0,0 +1,6 @@
|
||||
export function createDefs(...items) {
|
||||
return items.map(([type, Clazz]) => ({
|
||||
create: () => Clazz.create(),
|
||||
type
|
||||
}));
|
||||
}
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
import type { SubstrateApp } from '@zondax/ledger-substrate';
|
||||
import type { TransportType } from '@pezkuwi/hw-ledger-transports/types';
|
||||
import type { AccountOptions, LedgerAddress, LedgerSignature, LedgerVersion } from './types.js';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
type Chain = keyof typeof ledgerApps;
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* Legacy wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate)
|
||||
* @deprecated Use LedgerGeneric for up to date integration with ledger
|
||||
*/
|
||||
export declare class Ledger {
|
||||
#private;
|
||||
constructor(transport: TransportType, chain: Chain);
|
||||
/**
|
||||
* Returns the address associated with a specific account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddress(confirm?: boolean, accountOffset?: number, addressOffset?: number, { account, addressIndex, change }?: Partial<AccountOptions>): Promise<LedgerAddress>;
|
||||
/**
|
||||
* Returns the version of the Ledger application on the device
|
||||
*/
|
||||
getVersion(): Promise<LedgerVersion>;
|
||||
/**
|
||||
* Signs a transaction on the Ledger device
|
||||
*/
|
||||
sign(message: Uint8Array, accountOffset?: number, addressOffset?: number, options?: Partial<AccountOptions>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRaw(message: Uint8Array, accountOffset?: number, addressOffset?: number, options?: Partial<AccountOptions>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created SubstrateApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
withApp<T>(fn: (app: SubstrateApp) => Promise<T>): Promise<T>;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { newSubstrateApp } from '@zondax/ledger-substrate';
|
||||
import { transports } from '@pezkuwi/hw-ledger-transports';
|
||||
import { hexAddPrefix, u8aToBuffer, u8aWrapBytes } from '@pezkuwi/util';
|
||||
import { LEDGER_DEFAULT_ACCOUNT, LEDGER_DEFAULT_CHANGE, LEDGER_DEFAULT_INDEX, LEDGER_SUCCESS_CODE } from './constants.js';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
/** @internal Wraps a SubstrateApp call, checking the result for any errors which result in a rejection */
|
||||
async function wrapError(promise) {
|
||||
const result = await promise;
|
||||
if (result.return_code !== LEDGER_SUCCESS_CODE) {
|
||||
throw new Error(result.error_message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** @internal Wraps a sign/signRaw call and returns the associated signature */
|
||||
function sign(method, message, accountOffset = 0, addressOffset = 0, { account = LEDGER_DEFAULT_ACCOUNT, addressIndex = LEDGER_DEFAULT_INDEX, change = LEDGER_DEFAULT_CHANGE } = {}) {
|
||||
return async (app) => {
|
||||
const { signature } = await wrapError(app[method](account + accountOffset, change, addressIndex + addressOffset, u8aToBuffer(message)));
|
||||
return {
|
||||
signature: hexAddPrefix(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* Legacy wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate)
|
||||
* @deprecated Use LedgerGeneric for up to date integration with ledger
|
||||
*/
|
||||
export class Ledger {
|
||||
#ledgerName;
|
||||
#transportDef;
|
||||
#app = null;
|
||||
constructor(transport, chain) {
|
||||
const ledgerName = ledgerApps[chain];
|
||||
const transportDef = transports.find(({ type }) => type === transport);
|
||||
if (!ledgerName) {
|
||||
throw new Error(`Unsupported Ledger chain ${chain}`);
|
||||
}
|
||||
else if (!transportDef) {
|
||||
throw new Error(`Unsupported Ledger transport ${transport}`);
|
||||
}
|
||||
this.#ledgerName = ledgerName;
|
||||
this.#transportDef = transportDef;
|
||||
}
|
||||
/**
|
||||
* Returns the address associated with a specific account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddress(confirm = false, accountOffset = 0, addressOffset = 0, { account = LEDGER_DEFAULT_ACCOUNT, addressIndex = LEDGER_DEFAULT_INDEX, change = LEDGER_DEFAULT_CHANGE } = {}) {
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddress(account + accountOffset, change, addressIndex + addressOffset, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: hexAddPrefix(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns the version of the Ledger application on the device
|
||||
*/
|
||||
async getVersion() {
|
||||
return this.withApp(async (app) => {
|
||||
const { device_locked: isLocked, major, minor, patch, test_mode: isTestMode } = await wrapError(app.getVersion());
|
||||
return {
|
||||
isLocked,
|
||||
isTestMode,
|
||||
version: [major, minor, patch]
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Signs a transaction on the Ledger device
|
||||
*/
|
||||
async sign(message, accountOffset, addressOffset, options) {
|
||||
return this.withApp(sign('sign', message, accountOffset, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRaw(message, accountOffset, addressOffset, options) {
|
||||
return this.withApp(sign('signRaw', u8aWrapBytes(message), accountOffset, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created SubstrateApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
async withApp(fn) {
|
||||
try {
|
||||
if (!this.#app) {
|
||||
const transport = await this.#transportDef.create();
|
||||
// We need this override for the actual type passing - the Deno environment
|
||||
// is quite a bit stricter and it yields invalids between the two (specifically
|
||||
// since we mangle the imports from .default in the types for CJS/ESM and between
|
||||
// esm.sh versions this yields problematic outputs)
|
||||
//
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
this.#app = newSubstrateApp(transport, this.#ledgerName);
|
||||
}
|
||||
return await fn(this.#app);
|
||||
}
|
||||
catch (error) {
|
||||
this.#app = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import type { TransportType } from '@pezkuwi/hw-ledger-transports/types';
|
||||
import type { AccountOptionsGeneric, LedgerAddress, LedgerSignature, LedgerVersion } from './types.js';
|
||||
import { PolkadotGenericApp } from '@zondax/ledger-substrate';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
type Chain = keyof typeof ledgerApps;
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* A very basic wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate-js)
|
||||
*/
|
||||
export declare class LedgerGeneric {
|
||||
#private;
|
||||
constructor(transport: TransportType, chain: Chain, slip44: number, chainId?: string, metaUrl?: string);
|
||||
/**
|
||||
* @description Returns the address associated with a specific Ed25519 account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddress(ss58Prefix: number, confirm?: boolean, accountIndex?: number, addressOffset?: number): Promise<LedgerAddress>;
|
||||
/**
|
||||
* @description Returns the address associated with a specific ecdsa account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddressEcdsa(confirm?: boolean, accountIndex?: number, addressOffset?: number): Promise<LedgerAddress>;
|
||||
/**
|
||||
* @description Returns the version of the Ledger application on the device
|
||||
*/
|
||||
getVersion(): Promise<LedgerVersion>;
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
sign(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRaw(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device with Ecdsa. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
signEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a message with Ecdsa (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRawEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device provided some metadata.
|
||||
*/
|
||||
signWithMetadata(message: Uint8Array, accountIndex?: number, addressOffset?: number, options?: Partial<AccountOptionsGeneric>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device for an ecdsa signature provided some metadata.
|
||||
*/
|
||||
signWithMetadataEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number, options?: Partial<AccountOptionsGeneric>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created PolkadotGenericApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
withApp<T>(fn: (app: PolkadotGenericApp) => Promise<T>): Promise<T>;
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
import { PolkadotGenericApp } from '@zondax/ledger-substrate';
|
||||
import { transports } from '@pezkuwi/hw-ledger-transports';
|
||||
import { hexAddPrefix, u8aToBuffer, u8aWrapBytes } from '@pezkuwi/util';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
/** @internal Wraps a PolkadotGenericApp call, checking the result for any errors which result in a rejection */
|
||||
async function wrapError(promise) {
|
||||
let result;
|
||||
try {
|
||||
result = await promise;
|
||||
}
|
||||
catch (e) {
|
||||
// We check to see if the propogated error is the newer ResponseError type.
|
||||
// The response code use to be part of the result, but with the latest breaking changes from 0.42.x
|
||||
// the interface and it's types have completely changed.
|
||||
if (e.returnCode) {
|
||||
throw new Error(`${e.returnCode}: ${e.errorMessage}`);
|
||||
}
|
||||
throw new Error(e.message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** @internal Wraps a signEd25519/signRawEd25519 call and returns the associated signature */
|
||||
function sign(method, message, slip44, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
const { signature } = await wrapError(app[method](bip42Path, u8aToBuffer(message)));
|
||||
return {
|
||||
signature: hexAddPrefix(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signEcdsa/signRawEcdsa call and returns the associated signature */
|
||||
function signEcdsa(method, message, slip44, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
const { r, s, v } = await wrapError(app[method](bip42Path, u8aToBuffer(message)));
|
||||
const signature = Buffer.concat([r, s, v]);
|
||||
return {
|
||||
signature: hexAddPrefix(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signWithMetadataEd25519 call and returns the associated signature */
|
||||
function signWithMetadata(message, slip44, accountIndex = 0, addressOffset = 0, { metadata } = {}) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
if (!metadata) {
|
||||
throw new Error('The metadata option must be present when using signWithMetadata');
|
||||
}
|
||||
const bufferMsg = Buffer.from(message);
|
||||
const { signature } = await wrapError(app.signWithMetadataEd25519(bip42Path, bufferMsg, metadata));
|
||||
return {
|
||||
signature: hexAddPrefix(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signWithMetadataEcdsa call and returns the associated signature */
|
||||
function signWithMetadataEcdsa(message, slip44, accountIndex = 0, addressOffset = 0, { metadata } = {}) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
if (!metadata) {
|
||||
throw new Error('The metadata option must be present when using signWithMetadata');
|
||||
}
|
||||
const bufferMsg = Buffer.from(message);
|
||||
const { r, s, v } = await wrapError(app.signWithMetadataEcdsa(bip42Path, bufferMsg, metadata));
|
||||
const signature = Buffer.concat([r, s, v]);
|
||||
return {
|
||||
signature: hexAddPrefix(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* A very basic wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate-js)
|
||||
*/
|
||||
export class LedgerGeneric {
|
||||
#transportDef;
|
||||
#slip44;
|
||||
/**
|
||||
* The chainId is represented by the chains token in all lowercase. Example: Polkadot -> dot
|
||||
*/
|
||||
#chainId;
|
||||
/**
|
||||
* The metaUrl is seen as a server url that the underlying `PolkadotGenericApp` will use to
|
||||
* retrieve the signature given a tx blob, and a chainId. It is important to note that if you would like to avoid
|
||||
* having any network calls made, use `signWithMetadata`, and avoid `sign`.
|
||||
*/
|
||||
#metaUrl;
|
||||
#app = null;
|
||||
constructor(transport, chain, slip44, chainId, metaUrl) {
|
||||
const ledgerName = ledgerApps[chain];
|
||||
const transportDef = transports.find(({ type }) => type === transport);
|
||||
if (!ledgerName) {
|
||||
throw new Error(`Unsupported Ledger chain ${chain}`);
|
||||
}
|
||||
else if (!transportDef) {
|
||||
throw new Error(`Unsupported Ledger transport ${transport}`);
|
||||
}
|
||||
this.#metaUrl = metaUrl;
|
||||
this.#chainId = chainId;
|
||||
this.#slip44 = slip44;
|
||||
this.#transportDef = transportDef;
|
||||
}
|
||||
/**
|
||||
* @description Returns the address associated with a specific Ed25519 account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddress(ss58Prefix, confirm = false, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddressEd25519(bip42Path, ss58Prefix, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: hexAddPrefix(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Returns the address associated with a specific ecdsa account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddressEcdsa(confirm = false, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddressEcdsa(bip42Path, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: hexAddPrefix(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Returns the version of the Ledger application on the device
|
||||
*/
|
||||
async getVersion() {
|
||||
return this.withApp(async (app) => {
|
||||
const { deviceLocked: isLocked, major, minor, patch, testMode: isTestMode } = await wrapError(app.getVersion());
|
||||
return {
|
||||
isLocked: !!isLocked,
|
||||
isTestMode: !!isTestMode,
|
||||
version: [major || 0, minor || 0, patch || 0]
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
async sign(message, accountIndex, addressOffset) {
|
||||
return this.withApp(sign('signEd25519', message, this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRaw(message, accountIndex, addressOffset) {
|
||||
return this.withApp(sign('signRawEd25519', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device with Ecdsa. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
async signEcdsa(message, accountIndex, addressOffset) {
|
||||
return this.withApp(signEcdsa('signEcdsa', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a message with Ecdsa (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRawEcdsa(message, accountIndex, addressOffset) {
|
||||
return this.withApp(signEcdsa('signRawEcdsa', u8aWrapBytes(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device provided some metadata.
|
||||
*/
|
||||
async signWithMetadata(message, accountIndex, addressOffset, options) {
|
||||
return this.withApp(signWithMetadata(message, this.#slip44, accountIndex, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device for an ecdsa signature provided some metadata.
|
||||
*/
|
||||
async signWithMetadataEcdsa(message, accountIndex, addressOffset, options) {
|
||||
return this.withApp(signWithMetadataEcdsa(message, this.#slip44, accountIndex, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created PolkadotGenericApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
async withApp(fn) {
|
||||
try {
|
||||
if (!this.#app) {
|
||||
const transport = await this.#transportDef.create();
|
||||
// We need this override for the actual type passing - the Deno environment
|
||||
// is quite a bit stricter and it yields invalids between the two (specifically
|
||||
// since we mangle the imports from .default in the types for CJS/ESM and between
|
||||
// esm.sh versions this yields problematic outputs)
|
||||
//
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
this.#app = new PolkadotGenericApp(transport, this.#chainId, this.#metaUrl);
|
||||
}
|
||||
return await fn(this.#app);
|
||||
}
|
||||
catch (error) {
|
||||
this.#app = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export { Ledger } from './Ledger.js';
|
||||
export { LedgerGeneric } from './LedgerGeneric.js';
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Ledger } from './Ledger.js';
|
||||
export { LedgerGeneric } from './LedgerGeneric.js';
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
import type { SubstrateApp } from '@zondax/ledger-substrate';
|
||||
import type { TransportType } from '@pezkuwi/hw-ledger-transports/types';
|
||||
import type { AccountOptions, LedgerAddress, LedgerSignature, LedgerVersion } from './types.js';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
type Chain = keyof typeof ledgerApps;
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* Legacy wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate)
|
||||
* @deprecated Use LedgerGeneric for up to date integration with ledger
|
||||
*/
|
||||
export declare class Ledger {
|
||||
#private;
|
||||
constructor(transport: TransportType, chain: Chain);
|
||||
/**
|
||||
* Returns the address associated with a specific account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddress(confirm?: boolean, accountOffset?: number, addressOffset?: number, { account, addressIndex, change }?: Partial<AccountOptions>): Promise<LedgerAddress>;
|
||||
/**
|
||||
* Returns the version of the Ledger application on the device
|
||||
*/
|
||||
getVersion(): Promise<LedgerVersion>;
|
||||
/**
|
||||
* Signs a transaction on the Ledger device
|
||||
*/
|
||||
sign(message: Uint8Array, accountOffset?: number, addressOffset?: number, options?: Partial<AccountOptions>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRaw(message: Uint8Array, accountOffset?: number, addressOffset?: number, options?: Partial<AccountOptions>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created SubstrateApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
withApp<T>(fn: (app: SubstrateApp) => Promise<T>): Promise<T>;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Ledger = exports.packageInfo = void 0;
|
||||
const ledger_substrate_1 = require("@zondax/ledger-substrate");
|
||||
const hw_ledger_transports_1 = require("@pezkuwi/hw-ledger-transports");
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const constants_js_1 = require("./constants.js");
|
||||
const defaults_js_1 = require("./defaults.js");
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
/** @internal Wraps a SubstrateApp call, checking the result for any errors which result in a rejection */
|
||||
async function wrapError(promise) {
|
||||
const result = await promise;
|
||||
if (result.return_code !== constants_js_1.LEDGER_SUCCESS_CODE) {
|
||||
throw new Error(result.error_message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** @internal Wraps a sign/signRaw call and returns the associated signature */
|
||||
function sign(method, message, accountOffset = 0, addressOffset = 0, { account = constants_js_1.LEDGER_DEFAULT_ACCOUNT, addressIndex = constants_js_1.LEDGER_DEFAULT_INDEX, change = constants_js_1.LEDGER_DEFAULT_CHANGE } = {}) {
|
||||
return async (app) => {
|
||||
const { signature } = await wrapError(app[method](account + accountOffset, change, addressIndex + addressOffset, (0, util_1.u8aToBuffer)(message)));
|
||||
return {
|
||||
signature: (0, util_1.hexAddPrefix)(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* Legacy wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate)
|
||||
* @deprecated Use LedgerGeneric for up to date integration with ledger
|
||||
*/
|
||||
class Ledger {
|
||||
#ledgerName;
|
||||
#transportDef;
|
||||
#app = null;
|
||||
constructor(transport, chain) {
|
||||
const ledgerName = defaults_js_1.ledgerApps[chain];
|
||||
const transportDef = hw_ledger_transports_1.transports.find(({ type }) => type === transport);
|
||||
if (!ledgerName) {
|
||||
throw new Error(`Unsupported Ledger chain ${chain}`);
|
||||
}
|
||||
else if (!transportDef) {
|
||||
throw new Error(`Unsupported Ledger transport ${transport}`);
|
||||
}
|
||||
this.#ledgerName = ledgerName;
|
||||
this.#transportDef = transportDef;
|
||||
}
|
||||
/**
|
||||
* Returns the address associated with a specific account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddress(confirm = false, accountOffset = 0, addressOffset = 0, { account = constants_js_1.LEDGER_DEFAULT_ACCOUNT, addressIndex = constants_js_1.LEDGER_DEFAULT_INDEX, change = constants_js_1.LEDGER_DEFAULT_CHANGE } = {}) {
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddress(account + accountOffset, change, addressIndex + addressOffset, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: (0, util_1.hexAddPrefix)(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Returns the version of the Ledger application on the device
|
||||
*/
|
||||
async getVersion() {
|
||||
return this.withApp(async (app) => {
|
||||
const { device_locked: isLocked, major, minor, patch, test_mode: isTestMode } = await wrapError(app.getVersion());
|
||||
return {
|
||||
isLocked,
|
||||
isTestMode,
|
||||
version: [major, minor, patch]
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Signs a transaction on the Ledger device
|
||||
*/
|
||||
async sign(message, accountOffset, addressOffset, options) {
|
||||
return this.withApp(sign('sign', message, accountOffset, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRaw(message, accountOffset, addressOffset, options) {
|
||||
return this.withApp(sign('signRaw', (0, util_1.u8aWrapBytes)(message), accountOffset, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created SubstrateApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
async withApp(fn) {
|
||||
try {
|
||||
if (!this.#app) {
|
||||
const transport = await this.#transportDef.create();
|
||||
// We need this override for the actual type passing - the Deno environment
|
||||
// is quite a bit stricter and it yields invalids between the two (specifically
|
||||
// since we mangle the imports from .default in the types for CJS/ESM and between
|
||||
// esm.sh versions this yields problematic outputs)
|
||||
//
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
this.#app = (0, ledger_substrate_1.newSubstrateApp)(transport, this.#ledgerName);
|
||||
}
|
||||
return await fn(this.#app);
|
||||
}
|
||||
catch (error) {
|
||||
this.#app = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Ledger = Ledger;
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import type { TransportType } from '@pezkuwi/hw-ledger-transports/types';
|
||||
import type { AccountOptionsGeneric, LedgerAddress, LedgerSignature, LedgerVersion } from './types.js';
|
||||
import { PolkadotGenericApp } from '@zondax/ledger-substrate';
|
||||
import { ledgerApps } from './defaults.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
type Chain = keyof typeof ledgerApps;
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* A very basic wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate-js)
|
||||
*/
|
||||
export declare class LedgerGeneric {
|
||||
#private;
|
||||
constructor(transport: TransportType, chain: Chain, slip44: number, chainId?: string, metaUrl?: string);
|
||||
/**
|
||||
* @description Returns the address associated with a specific Ed25519 account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddress(ss58Prefix: number, confirm?: boolean, accountIndex?: number, addressOffset?: number): Promise<LedgerAddress>;
|
||||
/**
|
||||
* @description Returns the address associated with a specific ecdsa account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
getAddressEcdsa(confirm?: boolean, accountIndex?: number, addressOffset?: number): Promise<LedgerAddress>;
|
||||
/**
|
||||
* @description Returns the version of the Ledger application on the device
|
||||
*/
|
||||
getVersion(): Promise<LedgerVersion>;
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
sign(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRaw(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device with Ecdsa. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
signEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a message with Ecdsa (non-transactional) on the Ledger device
|
||||
*/
|
||||
signRawEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device provided some metadata.
|
||||
*/
|
||||
signWithMetadata(message: Uint8Array, accountIndex?: number, addressOffset?: number, options?: Partial<AccountOptionsGeneric>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device for an ecdsa signature provided some metadata.
|
||||
*/
|
||||
signWithMetadataEcdsa(message: Uint8Array, accountIndex?: number, addressOffset?: number, options?: Partial<AccountOptionsGeneric>): Promise<LedgerSignature>;
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created PolkadotGenericApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
withApp<T>(fn: (app: PolkadotGenericApp) => Promise<T>): Promise<T>;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LedgerGeneric = exports.packageInfo = void 0;
|
||||
const ledger_substrate_1 = require("@zondax/ledger-substrate");
|
||||
const hw_ledger_transports_1 = require("@pezkuwi/hw-ledger-transports");
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const defaults_js_1 = require("./defaults.js");
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
/** @internal Wraps a PolkadotGenericApp call, checking the result for any errors which result in a rejection */
|
||||
async function wrapError(promise) {
|
||||
let result;
|
||||
try {
|
||||
result = await promise;
|
||||
}
|
||||
catch (e) {
|
||||
// We check to see if the propogated error is the newer ResponseError type.
|
||||
// The response code use to be part of the result, but with the latest breaking changes from 0.42.x
|
||||
// the interface and it's types have completely changed.
|
||||
if (e.returnCode) {
|
||||
throw new Error(`${e.returnCode}: ${e.errorMessage}`);
|
||||
}
|
||||
throw new Error(e.message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** @internal Wraps a signEd25519/signRawEd25519 call and returns the associated signature */
|
||||
function sign(method, message, slip44, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
const { signature } = await wrapError(app[method](bip42Path, (0, util_1.u8aToBuffer)(message)));
|
||||
return {
|
||||
signature: (0, util_1.hexAddPrefix)(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signEcdsa/signRawEcdsa call and returns the associated signature */
|
||||
function signEcdsa(method, message, slip44, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
const { r, s, v } = await wrapError(app[method](bip42Path, (0, util_1.u8aToBuffer)(message)));
|
||||
const signature = Buffer.concat([r, s, v]);
|
||||
return {
|
||||
signature: (0, util_1.hexAddPrefix)(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signWithMetadataEd25519 call and returns the associated signature */
|
||||
function signWithMetadata(message, slip44, accountIndex = 0, addressOffset = 0, { metadata } = {}) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
if (!metadata) {
|
||||
throw new Error('The metadata option must be present when using signWithMetadata');
|
||||
}
|
||||
const bufferMsg = Buffer.from(message);
|
||||
const { signature } = await wrapError(app.signWithMetadataEd25519(bip42Path, bufferMsg, metadata));
|
||||
return {
|
||||
signature: (0, util_1.hexAddPrefix)(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/** @internal Wraps a signWithMetadataEcdsa call and returns the associated signature */
|
||||
function signWithMetadataEcdsa(message, slip44, accountIndex = 0, addressOffset = 0, { metadata } = {}) {
|
||||
const bip42Path = `m/44'/${slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return async (app) => {
|
||||
if (!metadata) {
|
||||
throw new Error('The metadata option must be present when using signWithMetadata');
|
||||
}
|
||||
const bufferMsg = Buffer.from(message);
|
||||
const { r, s, v } = await wrapError(app.signWithMetadataEcdsa(bip42Path, bufferMsg, metadata));
|
||||
const signature = Buffer.concat([r, s, v]);
|
||||
return {
|
||||
signature: (0, util_1.hexAddPrefix)(signature.toString('hex'))
|
||||
};
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @name Ledger
|
||||
*
|
||||
* @description
|
||||
* A very basic wrapper for a ledger app -
|
||||
* - it connects automatically on use, creating an underlying interface as required
|
||||
* - Promises reject with errors (unwrapped errors from @zondax/ledger-substrate-js)
|
||||
*/
|
||||
class LedgerGeneric {
|
||||
#transportDef;
|
||||
#slip44;
|
||||
/**
|
||||
* The chainId is represented by the chains token in all lowercase. Example: Polkadot -> dot
|
||||
*/
|
||||
#chainId;
|
||||
/**
|
||||
* The metaUrl is seen as a server url that the underlying `PolkadotGenericApp` will use to
|
||||
* retrieve the signature given a tx blob, and a chainId. It is important to note that if you would like to avoid
|
||||
* having any network calls made, use `signWithMetadata`, and avoid `sign`.
|
||||
*/
|
||||
#metaUrl;
|
||||
#app = null;
|
||||
constructor(transport, chain, slip44, chainId, metaUrl) {
|
||||
const ledgerName = defaults_js_1.ledgerApps[chain];
|
||||
const transportDef = hw_ledger_transports_1.transports.find(({ type }) => type === transport);
|
||||
if (!ledgerName) {
|
||||
throw new Error(`Unsupported Ledger chain ${chain}`);
|
||||
}
|
||||
else if (!transportDef) {
|
||||
throw new Error(`Unsupported Ledger transport ${transport}`);
|
||||
}
|
||||
this.#metaUrl = metaUrl;
|
||||
this.#chainId = chainId;
|
||||
this.#slip44 = slip44;
|
||||
this.#transportDef = transportDef;
|
||||
}
|
||||
/**
|
||||
* @description Returns the address associated with a specific Ed25519 account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddress(ss58Prefix, confirm = false, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddressEd25519(bip42Path, ss58Prefix, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: (0, util_1.hexAddPrefix)(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Returns the address associated with a specific ecdsa account & address offset. Optionally
|
||||
* asks for on-device confirmation
|
||||
*/
|
||||
async getAddressEcdsa(confirm = false, accountIndex = 0, addressOffset = 0) {
|
||||
const bip42Path = `m/44'/${this.#slip44}'/${accountIndex}'/${0}'/${addressOffset}'`;
|
||||
return this.withApp(async (app) => {
|
||||
const { address, pubKey } = await wrapError(app.getAddressEcdsa(bip42Path, confirm));
|
||||
return {
|
||||
address,
|
||||
publicKey: (0, util_1.hexAddPrefix)(pubKey)
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Returns the version of the Ledger application on the device
|
||||
*/
|
||||
async getVersion() {
|
||||
return this.withApp(async (app) => {
|
||||
const { deviceLocked: isLocked, major, minor, patch, testMode: isTestMode } = await wrapError(app.getVersion());
|
||||
return {
|
||||
isLocked: !!isLocked,
|
||||
isTestMode: !!isTestMode,
|
||||
version: [major || 0, minor || 0, patch || 0]
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
async sign(message, accountIndex, addressOffset) {
|
||||
return this.withApp(sign('signEd25519', message, this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a message (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRaw(message, accountIndex, addressOffset) {
|
||||
return this.withApp(sign('signRawEd25519', (0, util_1.u8aWrapBytes)(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the Ledger device with Ecdsa. This requires the LedgerGeneric class to be instantiated with `chainId`, and `metaUrl`
|
||||
*/
|
||||
async signEcdsa(message, accountIndex, addressOffset) {
|
||||
return this.withApp(signEcdsa('signEcdsa', (0, util_1.u8aWrapBytes)(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a message with Ecdsa (non-transactional) on the Ledger device
|
||||
*/
|
||||
async signRawEcdsa(message, accountIndex, addressOffset) {
|
||||
return this.withApp(signEcdsa('signRawEcdsa', (0, util_1.u8aWrapBytes)(message), this.#slip44, accountIndex, addressOffset));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device provided some metadata.
|
||||
*/
|
||||
async signWithMetadata(message, accountIndex, addressOffset, options) {
|
||||
return this.withApp(signWithMetadata(message, this.#slip44, accountIndex, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @description Signs a transaction on the ledger device for an ecdsa signature provided some metadata.
|
||||
*/
|
||||
async signWithMetadataEcdsa(message, accountIndex, addressOffset, options) {
|
||||
return this.withApp(signWithMetadataEcdsa(message, this.#slip44, accountIndex, addressOffset, options));
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a created PolkadotGenericApp to perform operations against. Generally
|
||||
* this is only used internally, to ensure consistent bahavior.
|
||||
*/
|
||||
async withApp(fn) {
|
||||
try {
|
||||
if (!this.#app) {
|
||||
const transport = await this.#transportDef.create();
|
||||
// We need this override for the actual type passing - the Deno environment
|
||||
// is quite a bit stricter and it yields invalids between the two (specifically
|
||||
// since we mangle the imports from .default in the types for CJS/ESM and between
|
||||
// esm.sh versions this yields problematic outputs)
|
||||
//
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
this.#app = new ledger_substrate_1.PolkadotGenericApp(transport, this.#chainId, this.#metaUrl);
|
||||
}
|
||||
return await fn(this.#app);
|
||||
}
|
||||
catch (error) {
|
||||
this.#app = null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.LedgerGeneric = LedgerGeneric;
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export { Ledger } from './Ledger.js';
|
||||
export { LedgerGeneric } from './LedgerGeneric.js';
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LedgerGeneric = exports.Ledger = void 0;
|
||||
var Ledger_js_1 = require("./Ledger.js");
|
||||
Object.defineProperty(exports, "Ledger", { enumerable: true, get: function () { return Ledger_js_1.Ledger; } });
|
||||
var LedgerGeneric_js_1 = require("./LedgerGeneric.js");
|
||||
Object.defineProperty(exports, "LedgerGeneric", { enumerable: true, get: function () { return LedgerGeneric_js_1.LedgerGeneric; } });
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export declare const LEDGER_DEFAULT_ACCOUNT = 2147483648;
|
||||
export declare const LEDGER_DEFAULT_CHANGE = 2147483648;
|
||||
export declare const LEDGER_DEFAULT_INDEX = 2147483648;
|
||||
export declare const LEDGER_SUCCESS_CODE = 36864;
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LEDGER_SUCCESS_CODE = exports.LEDGER_DEFAULT_INDEX = exports.LEDGER_DEFAULT_CHANGE = exports.LEDGER_DEFAULT_ACCOUNT = void 0;
|
||||
exports.LEDGER_DEFAULT_ACCOUNT = 0x80000000;
|
||||
exports.LEDGER_DEFAULT_CHANGE = 0x80000000;
|
||||
exports.LEDGER_DEFAULT_INDEX = 0x80000000;
|
||||
exports.LEDGER_SUCCESS_CODE = 0x9000;
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
export declare const prevLedgerRecord: Record<string, string>;
|
||||
export declare const genericLedgerApps: {
|
||||
bittensor: string;
|
||||
creditcoin3: string;
|
||||
dentnet: string;
|
||||
encointer: string;
|
||||
frequency: string;
|
||||
integritee: string;
|
||||
liberland: string;
|
||||
mythos: string;
|
||||
polimec: string;
|
||||
vara: string;
|
||||
};
|
||||
export declare const ledgerApps: Record<string, string>;
|
||||
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ledgerApps = exports.genericLedgerApps = exports.prevLedgerRecord = void 0;
|
||||
exports.prevLedgerRecord = {
|
||||
acala: 'Acala',
|
||||
ajuna: 'Ajuna',
|
||||
'aleph-node': 'AlephZero',
|
||||
astar: 'Astar',
|
||||
bifrost: 'Bifrost',
|
||||
'bifrost-kusama': 'BifrostKusama',
|
||||
centrifuge: 'Centrifuge',
|
||||
composable: 'Composable',
|
||||
darwinia: 'Darwinia',
|
||||
'dock-mainnet': 'Dock',
|
||||
edgeware: 'Edgeware',
|
||||
enjin: 'Enjin',
|
||||
equilibrium: 'Equilibrium',
|
||||
genshiro: 'Genshiro',
|
||||
hydradx: 'HydraDX',
|
||||
'interlay-parachain': 'Interlay',
|
||||
karura: 'Karura',
|
||||
khala: 'Khala',
|
||||
kusama: 'Kusama',
|
||||
matrixchain: 'Matrixchain',
|
||||
nodle: 'Nodle',
|
||||
origintrail: 'OriginTrail',
|
||||
parallel: 'Parallel',
|
||||
peaq: 'Peaq',
|
||||
pendulum: 'Pendulum',
|
||||
phala: 'Phala',
|
||||
picasso: 'Picasso',
|
||||
polkadex: 'Polkadex',
|
||||
polkadot: 'Polkadot',
|
||||
polymesh: 'Polymesh',
|
||||
quartz: 'Quartz',
|
||||
sora: 'Sora',
|
||||
stafi: 'Stafi',
|
||||
statemine: 'Statemine',
|
||||
statemint: 'Statemint',
|
||||
ternoa: 'Ternoa',
|
||||
unique: 'Unique',
|
||||
vtb: 'VTB',
|
||||
xxnetwork: 'XXNetwork',
|
||||
zeitgeist: 'Zeitgeist'
|
||||
};
|
||||
exports.genericLedgerApps = {
|
||||
bittensor: 'Bittensor',
|
||||
creditcoin3: 'Creditcoin3',
|
||||
dentnet: 'DENTNet',
|
||||
encointer: 'Encointer',
|
||||
frequency: 'Frequency',
|
||||
integritee: 'Integritee',
|
||||
liberland: 'Liberland',
|
||||
mythos: 'Mythos',
|
||||
polimec: 'Polimec',
|
||||
vara: 'Vara'
|
||||
};
|
||||
exports.ledgerApps = {
|
||||
...exports.prevLedgerRecord,
|
||||
...exports.genericLedgerApps
|
||||
};
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import './packageDetect.js';
|
||||
export * from './bundle.js';
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
require("./packageDetect.js");
|
||||
tslib_1.__exportStar(require("./bundle.js"), exports);
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const packageInfo_1 = require("@pezkuwi/hw-ledger-transports/cjs/packageInfo");
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const packageInfo_2 = require("@pezkuwi/util/cjs/packageInfo");
|
||||
const packageInfo_js_1 = require("./packageInfo.js");
|
||||
(0, util_1.detectPackage)(packageInfo_js_1.packageInfo, null, [packageInfo_1.packageInfo, packageInfo_2.packageInfo]);
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export declare const packageInfo: {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
version: string;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.packageInfo = void 0;
|
||||
exports.packageInfo = { name: '@pezkuwi/hw-ledger', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '14.0.10' };
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
import type { HexString } from '@pezkuwi/util/types';
|
||||
/**
|
||||
* Legacy Type that works with the `Ledger` class.
|
||||
*/
|
||||
export interface AccountOptions {
|
||||
/** The index of the account */
|
||||
account: number;
|
||||
/** The index of the address */
|
||||
addressIndex: number;
|
||||
/** The change to apply */
|
||||
change: number;
|
||||
}
|
||||
export interface AccountOptionsGeneric extends AccountOptions {
|
||||
/** Option for PolkadotGenericApp.signWithMetadata */
|
||||
metadata: Buffer;
|
||||
}
|
||||
export interface LedgerAddress {
|
||||
/** The ss58 encoded address */
|
||||
address: string;
|
||||
/** The hex-encoded publicKey */
|
||||
publicKey: HexString;
|
||||
}
|
||||
export interface LedgerSignature {
|
||||
/** A hex-encoded signature, as generated by the device */
|
||||
signature: HexString;
|
||||
}
|
||||
export interface LedgerVersion {
|
||||
/** Indicator flag for locked status */
|
||||
isLocked: boolean;
|
||||
/** Indicator flag for testmode status */
|
||||
isTestMode: boolean;
|
||||
/** The software version for this device */
|
||||
version: [major: number, minor: number, patch: number];
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
export declare const LEDGER_DEFAULT_ACCOUNT = 2147483648;
|
||||
export declare const LEDGER_DEFAULT_CHANGE = 2147483648;
|
||||
export declare const LEDGER_DEFAULT_INDEX = 2147483648;
|
||||
export declare const LEDGER_SUCCESS_CODE = 36864;
|
||||
@@ -0,0 +1,4 @@
|
||||
export const LEDGER_DEFAULT_ACCOUNT = 0x80000000;
|
||||
export const LEDGER_DEFAULT_CHANGE = 0x80000000;
|
||||
export const LEDGER_DEFAULT_INDEX = 0x80000000;
|
||||
export const LEDGER_SUCCESS_CODE = 0x9000;
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
export declare const prevLedgerRecord: Record<string, string>;
|
||||
export declare const genericLedgerApps: {
|
||||
bittensor: string;
|
||||
creditcoin3: string;
|
||||
dentnet: string;
|
||||
encointer: string;
|
||||
frequency: string;
|
||||
integritee: string;
|
||||
liberland: string;
|
||||
mythos: string;
|
||||
polimec: string;
|
||||
vara: string;
|
||||
};
|
||||
export declare const ledgerApps: Record<string, string>;
|
||||
@@ -0,0 +1,58 @@
|
||||
export const prevLedgerRecord = {
|
||||
acala: 'Acala',
|
||||
ajuna: 'Ajuna',
|
||||
'aleph-node': 'AlephZero',
|
||||
astar: 'Astar',
|
||||
bifrost: 'Bifrost',
|
||||
'bifrost-kusama': 'BifrostKusama',
|
||||
centrifuge: 'Centrifuge',
|
||||
composable: 'Composable',
|
||||
darwinia: 'Darwinia',
|
||||
'dock-mainnet': 'Dock',
|
||||
edgeware: 'Edgeware',
|
||||
enjin: 'Enjin',
|
||||
equilibrium: 'Equilibrium',
|
||||
genshiro: 'Genshiro',
|
||||
hydradx: 'HydraDX',
|
||||
'interlay-parachain': 'Interlay',
|
||||
karura: 'Karura',
|
||||
khala: 'Khala',
|
||||
kusama: 'Kusama',
|
||||
matrixchain: 'Matrixchain',
|
||||
nodle: 'Nodle',
|
||||
origintrail: 'OriginTrail',
|
||||
parallel: 'Parallel',
|
||||
peaq: 'Peaq',
|
||||
pendulum: 'Pendulum',
|
||||
phala: 'Phala',
|
||||
picasso: 'Picasso',
|
||||
polkadex: 'Polkadex',
|
||||
polkadot: 'Polkadot',
|
||||
polymesh: 'Polymesh',
|
||||
quartz: 'Quartz',
|
||||
sora: 'Sora',
|
||||
stafi: 'Stafi',
|
||||
statemine: 'Statemine',
|
||||
statemint: 'Statemint',
|
||||
ternoa: 'Ternoa',
|
||||
unique: 'Unique',
|
||||
vtb: 'VTB',
|
||||
xxnetwork: 'XXNetwork',
|
||||
zeitgeist: 'Zeitgeist'
|
||||
};
|
||||
export const genericLedgerApps = {
|
||||
bittensor: 'Bittensor',
|
||||
creditcoin3: 'Creditcoin3',
|
||||
dentnet: 'DENTNet',
|
||||
encointer: 'Encointer',
|
||||
frequency: 'Frequency',
|
||||
integritee: 'Integritee',
|
||||
liberland: 'Liberland',
|
||||
mythos: 'Mythos',
|
||||
polimec: 'Polimec',
|
||||
vara: 'Vara'
|
||||
};
|
||||
export const ledgerApps = {
|
||||
...prevLedgerRecord,
|
||||
...genericLedgerApps
|
||||
};
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import './packageDetect.js';
|
||||
export * from './bundle.js';
|
||||
@@ -0,0 +1,2 @@
|
||||
import './packageDetect.js';
|
||||
export * from './bundle.js';
|
||||
@@ -14,14 +14,164 @@
|
||||
},
|
||||
"sideEffects": [
|
||||
"./packageDetect.js",
|
||||
"./packageDetect.cjs"
|
||||
"./cjs/packageDetect.js"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "14.0.10",
|
||||
"main": "index.js",
|
||||
"version": "14.0.11",
|
||||
"main": "./cjs/index.js",
|
||||
"module": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"exports": {
|
||||
"./cjs/package.json": "./cjs/package.json",
|
||||
"./cjs/*": "./cjs/*.js",
|
||||
".": {
|
||||
"module": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/index.d.ts",
|
||||
"default": "./cjs/index.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
}
|
||||
},
|
||||
"./bundle": {
|
||||
"module": {
|
||||
"types": "./bundle.d.ts",
|
||||
"default": "./bundle.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/bundle.d.ts",
|
||||
"default": "./cjs/bundle.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./bundle.d.ts",
|
||||
"default": "./bundle.js"
|
||||
}
|
||||
},
|
||||
"./constants": {
|
||||
"module": {
|
||||
"types": "./constants.d.ts",
|
||||
"default": "./constants.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/constants.d.ts",
|
||||
"default": "./cjs/constants.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./constants.d.ts",
|
||||
"default": "./constants.js"
|
||||
}
|
||||
},
|
||||
"./defaults": {
|
||||
"module": {
|
||||
"types": "./defaults.d.ts",
|
||||
"default": "./defaults.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/defaults.d.ts",
|
||||
"default": "./cjs/defaults.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./defaults.d.ts",
|
||||
"default": "./defaults.js"
|
||||
}
|
||||
},
|
||||
"./Ledger": {
|
||||
"module": {
|
||||
"types": "./Ledger.d.ts",
|
||||
"default": "./Ledger.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/Ledger.d.ts",
|
||||
"default": "./cjs/Ledger.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./Ledger.d.ts",
|
||||
"default": "./Ledger.js"
|
||||
}
|
||||
},
|
||||
"./LedgerGeneric": {
|
||||
"module": {
|
||||
"types": "./LedgerGeneric.d.ts",
|
||||
"default": "./LedgerGeneric.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/LedgerGeneric.d.ts",
|
||||
"default": "./cjs/LedgerGeneric.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./LedgerGeneric.d.ts",
|
||||
"default": "./LedgerGeneric.js"
|
||||
}
|
||||
},
|
||||
"./package.json": {
|
||||
"require": "./cjs/package.json",
|
||||
"default": "./package.json"
|
||||
},
|
||||
"./packageDetect": {
|
||||
"module": {
|
||||
"types": "./packageDetect.d.ts",
|
||||
"default": "./packageDetect.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageDetect.d.ts",
|
||||
"default": "./cjs/packageDetect.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageDetect.d.ts",
|
||||
"default": "./packageDetect.js"
|
||||
}
|
||||
},
|
||||
"./packageInfo.js": {
|
||||
"module": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageInfo.d.ts",
|
||||
"default": "./cjs/packageInfo.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
}
|
||||
},
|
||||
"./packageInfo": {
|
||||
"module": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/packageInfo.d.ts",
|
||||
"default": "./cjs/packageInfo.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./packageInfo.d.ts",
|
||||
"default": "./packageInfo.js"
|
||||
}
|
||||
},
|
||||
"./types": {
|
||||
"module": {
|
||||
"types": "./types.d.ts",
|
||||
"default": "./types.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./cjs/types.d.ts",
|
||||
"default": "./cjs/types.js"
|
||||
},
|
||||
"default": {
|
||||
"types": "./types.d.ts",
|
||||
"default": "./types.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@pezkuwi/hw-ledger-transports": "workspace:*",
|
||||
"@pezkuwi/util": "workspace:*",
|
||||
"@pezkuwi/hw-ledger-transports": "14.0.11",
|
||||
"@pezkuwi/util": "14.0.11",
|
||||
"@zondax/ledger-substrate": "1.1.1",
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { packageInfo as transportInfo } from '@pezkuwi/hw-ledger-transports/packageInfo';
|
||||
import { detectPackage } from '@pezkuwi/util';
|
||||
import { packageInfo as utilInfo } from '@pezkuwi/util/packageInfo';
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
detectPackage(packageInfo, null, [transportInfo, utilInfo]);
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
export declare const packageInfo: {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
version: string;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export const packageInfo = { name: '@pezkuwi/hw-ledger', path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '14.0.10' };
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
import type { HexString } from '@pezkuwi/util/types';
|
||||
/**
|
||||
* Legacy Type that works with the `Ledger` class.
|
||||
*/
|
||||
export interface AccountOptions {
|
||||
/** The index of the account */
|
||||
account: number;
|
||||
/** The index of the address */
|
||||
addressIndex: number;
|
||||
/** The change to apply */
|
||||
change: number;
|
||||
}
|
||||
export interface AccountOptionsGeneric extends AccountOptions {
|
||||
/** Option for PolkadotGenericApp.signWithMetadata */
|
||||
metadata: Buffer;
|
||||
}
|
||||
export interface LedgerAddress {
|
||||
/** The ss58 encoded address */
|
||||
address: string;
|
||||
/** The hex-encoded publicKey */
|
||||
publicKey: HexString;
|
||||
}
|
||||
export interface LedgerSignature {
|
||||
/** A hex-encoded signature, as generated by the device */
|
||||
signature: HexString;
|
||||
}
|
||||
export interface LedgerVersion {
|
||||
/** Indicator flag for locked status */
|
||||
isLocked: boolean;
|
||||
/** Indicator flag for testmode status */
|
||||
isTestMode: boolean;
|
||||
/** The software version for this device */
|
||||
version: [major: number, minor: number, patch: number];
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,553 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@pezkuwi/util-crypto'), require('@pezkuwi/util')) :
|
||||
typeof define === 'function' && define.amd ? define(['exports', '@pezkuwi/util-crypto', '@pezkuwi/util'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.pezkuwiKeyring = {}, global.pezkuwiUtilCrypto, global.pezkuwiUtil));
|
||||
})(this, (function (exports, utilCrypto, util) { 'use strict';
|
||||
|
||||
const global = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : window;
|
||||
|
||||
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
||||
const PAIR_DIV = new Uint8Array([161, 35, 3, 33, 0]);
|
||||
const PAIR_HDR = new Uint8Array([48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
|
||||
const PUB_LENGTH = 32;
|
||||
const SEC_LENGTH = 64;
|
||||
const SEED_LENGTH = 32;
|
||||
|
||||
const SEED_OFFSET = PAIR_HDR.length;
|
||||
function decodePair(passphrase, encrypted, _encType) {
|
||||
const encType = Array.isArray(_encType) || _encType === undefined
|
||||
? _encType
|
||||
: [_encType];
|
||||
const decrypted = utilCrypto.jsonDecryptData(encrypted, passphrase, encType);
|
||||
const header = decrypted.subarray(0, PAIR_HDR.length);
|
||||
if (!util.u8aEq(header, PAIR_HDR)) {
|
||||
throw new Error('Invalid encoding header found in body');
|
||||
}
|
||||
let secretKey = decrypted.subarray(SEED_OFFSET, SEED_OFFSET + SEC_LENGTH);
|
||||
let divOffset = SEED_OFFSET + SEC_LENGTH;
|
||||
let divider = decrypted.subarray(divOffset, divOffset + PAIR_DIV.length);
|
||||
if (!util.u8aEq(divider, PAIR_DIV)) {
|
||||
divOffset = SEED_OFFSET + SEED_LENGTH;
|
||||
secretKey = decrypted.subarray(SEED_OFFSET, divOffset);
|
||||
divider = decrypted.subarray(divOffset, divOffset + PAIR_DIV.length);
|
||||
if (!util.u8aEq(divider, PAIR_DIV)) {
|
||||
throw new Error('Invalid encoding divider found in body');
|
||||
}
|
||||
}
|
||||
const pubOffset = divOffset + PAIR_DIV.length;
|
||||
const publicKey = decrypted.subarray(pubOffset, pubOffset + PUB_LENGTH);
|
||||
return {
|
||||
publicKey,
|
||||
secretKey
|
||||
};
|
||||
}
|
||||
|
||||
function encodePair({ publicKey, secretKey }, passphrase) {
|
||||
if (!secretKey) {
|
||||
throw new Error('Expected a valid secretKey to be passed to encode');
|
||||
}
|
||||
const encoded = util.u8aConcat(PAIR_HDR, secretKey, PAIR_DIV, publicKey);
|
||||
if (!passphrase) {
|
||||
return encoded;
|
||||
}
|
||||
const { params, password, salt } = utilCrypto.scryptEncode(passphrase);
|
||||
const { encrypted, nonce } = utilCrypto.naclEncrypt(encoded, password.subarray(0, 32));
|
||||
return util.u8aConcat(utilCrypto.scryptToU8a(salt, params), nonce, encrypted);
|
||||
}
|
||||
|
||||
function pairToJson(type, { address, meta }, encoded, isEncrypted) {
|
||||
return util.objectSpread(utilCrypto.jsonEncryptFormat(encoded, ['pkcs8', type], isEncrypted), {
|
||||
address,
|
||||
meta
|
||||
});
|
||||
}
|
||||
|
||||
const SIG_TYPE_NONE = new Uint8Array();
|
||||
const TYPE_FROM_SEED = {
|
||||
ecdsa: utilCrypto.secp256k1PairFromSeed,
|
||||
ed25519: utilCrypto.ed25519PairFromSeed,
|
||||
ethereum: utilCrypto.secp256k1PairFromSeed,
|
||||
sr25519: utilCrypto.sr25519PairFromSeed
|
||||
};
|
||||
const TYPE_PREFIX = {
|
||||
ecdsa: new Uint8Array([2]),
|
||||
ed25519: new Uint8Array([0]),
|
||||
ethereum: new Uint8Array([2]),
|
||||
sr25519: new Uint8Array([1])
|
||||
};
|
||||
const TYPE_SIGNATURE = {
|
||||
ecdsa: (m, p) => utilCrypto.secp256k1Sign(m, p, 'blake2'),
|
||||
ed25519: utilCrypto.ed25519Sign,
|
||||
ethereum: (m, p) => utilCrypto.secp256k1Sign(m, p, 'keccak'),
|
||||
sr25519: utilCrypto.sr25519Sign
|
||||
};
|
||||
const TYPE_ADDRESS = {
|
||||
ecdsa: (p) => p.length > 32 ? utilCrypto.blake2AsU8a(p) : p,
|
||||
ed25519: (p) => p,
|
||||
ethereum: (p) => p.length === 20 ? p : utilCrypto.keccakAsU8a(utilCrypto.secp256k1Expand(p)),
|
||||
sr25519: (p) => p
|
||||
};
|
||||
function isLocked(secretKey) {
|
||||
return !secretKey || util.u8aEmpty(secretKey);
|
||||
}
|
||||
function vrfHash(proof, context, extra) {
|
||||
return utilCrypto.blake2AsU8a(util.u8aConcat(context || '', extra || '', proof));
|
||||
}
|
||||
function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encoded = null, encTypes) {
|
||||
const decodePkcs8 = (passphrase, userEncoded) => {
|
||||
const decoded = decodePair(passphrase, userEncoded || encoded, encTypes);
|
||||
if (decoded.secretKey.length === 64) {
|
||||
publicKey = decoded.publicKey;
|
||||
secretKey = decoded.secretKey;
|
||||
}
|
||||
else {
|
||||
const pair = TYPE_FROM_SEED[type](decoded.secretKey);
|
||||
publicKey = pair.publicKey;
|
||||
secretKey = pair.secretKey;
|
||||
}
|
||||
};
|
||||
const recode = (passphrase) => {
|
||||
isLocked(secretKey) && encoded && decodePkcs8(passphrase, encoded);
|
||||
encoded = encodePair({ publicKey, secretKey }, passphrase);
|
||||
encTypes = undefined;
|
||||
return encoded;
|
||||
};
|
||||
const encodeAddress = () => {
|
||||
const raw = TYPE_ADDRESS[type](publicKey);
|
||||
return type === 'ethereum'
|
||||
? utilCrypto.ethereumEncode(raw)
|
||||
: toSS58(raw);
|
||||
};
|
||||
return {
|
||||
get address() {
|
||||
return encodeAddress();
|
||||
},
|
||||
get addressRaw() {
|
||||
const raw = TYPE_ADDRESS[type](publicKey);
|
||||
return type === 'ethereum'
|
||||
? raw.slice(-20)
|
||||
: raw;
|
||||
},
|
||||
get isLocked() {
|
||||
return isLocked(secretKey);
|
||||
},
|
||||
get meta() {
|
||||
return meta;
|
||||
},
|
||||
get publicKey() {
|
||||
return publicKey;
|
||||
},
|
||||
get type() {
|
||||
return type;
|
||||
},
|
||||
decodePkcs8,
|
||||
derive: (suri, meta) => {
|
||||
if (type === 'ethereum') {
|
||||
throw new Error('Unable to derive on this keypair');
|
||||
}
|
||||
else if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot derive on a locked keypair');
|
||||
}
|
||||
const { path } = utilCrypto.keyExtractPath(suri);
|
||||
const derived = utilCrypto.keyFromPath({ publicKey, secretKey }, path, type);
|
||||
return createPair({ toSS58, type }, derived, meta, null);
|
||||
},
|
||||
encodePkcs8: (passphrase) => {
|
||||
return recode(passphrase);
|
||||
},
|
||||
lock: () => {
|
||||
secretKey = new Uint8Array();
|
||||
},
|
||||
setMeta: (additional) => {
|
||||
meta = util.objectSpread({}, meta, additional);
|
||||
},
|
||||
sign: (message, options = {}) => {
|
||||
if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot sign with a locked key pair');
|
||||
}
|
||||
return util.u8aConcat(options.withType
|
||||
? TYPE_PREFIX[type]
|
||||
: SIG_TYPE_NONE, TYPE_SIGNATURE[type](util.u8aToU8a(message), { publicKey, secretKey }));
|
||||
},
|
||||
toJson: (passphrase) => {
|
||||
const address = ['ecdsa', 'ethereum'].includes(type)
|
||||
? publicKey.length === 20
|
||||
? util.u8aToHex(publicKey)
|
||||
: util.u8aToHex(utilCrypto.secp256k1Compress(publicKey))
|
||||
: encodeAddress();
|
||||
return pairToJson(type, { address, meta }, recode(passphrase), !!passphrase);
|
||||
},
|
||||
unlock: (passphrase) => {
|
||||
return decodePkcs8(passphrase);
|
||||
},
|
||||
verify: (message, signature, signerPublic) => {
|
||||
return utilCrypto.signatureVerify(message, signature, TYPE_ADDRESS[type](util.u8aToU8a(signerPublic))).isValid;
|
||||
},
|
||||
vrfSign: (message, context, extra) => {
|
||||
if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot sign with a locked key pair');
|
||||
}
|
||||
if (type === 'sr25519') {
|
||||
return utilCrypto.sr25519VrfSign(message, { secretKey }, context, extra);
|
||||
}
|
||||
const proof = TYPE_SIGNATURE[type](util.u8aToU8a(message), { publicKey, secretKey });
|
||||
return util.u8aConcat(vrfHash(proof, context, extra), proof);
|
||||
},
|
||||
vrfVerify: (message, vrfResult, signerPublic, context, extra) => {
|
||||
if (type === 'sr25519') {
|
||||
return utilCrypto.sr25519VrfVerify(message, vrfResult, publicKey, context, extra);
|
||||
}
|
||||
const result = utilCrypto.signatureVerify(message, util.u8aConcat(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type](util.u8aToU8a(signerPublic)));
|
||||
return result.isValid && util.u8aEq(vrfResult.subarray(0, 32), vrfHash(vrfResult.subarray(32), context, extra));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const DEV_PHRASE = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk';
|
||||
const DEV_SEED = '0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e';
|
||||
|
||||
class Pairs {
|
||||
#map = {};
|
||||
add(pair) {
|
||||
this.#map[utilCrypto.decodeAddress(pair.address).toString()] = pair;
|
||||
return pair;
|
||||
}
|
||||
all() {
|
||||
return Object.values(this.#map);
|
||||
}
|
||||
get(address) {
|
||||
const pair = this.#map[utilCrypto.decodeAddress(address).toString()];
|
||||
if (!pair) {
|
||||
throw new Error(`Unable to retrieve keypair '${util.isU8a(address) || util.isHex(address)
|
||||
? util.u8aToHex(util.u8aToU8a(address))
|
||||
: address}'`);
|
||||
}
|
||||
return pair;
|
||||
}
|
||||
remove(address) {
|
||||
delete this.#map[utilCrypto.decodeAddress(address).toString()];
|
||||
}
|
||||
}
|
||||
|
||||
const PairFromSeed = {
|
||||
ecdsa: (seed) => utilCrypto.secp256k1PairFromSeed(seed),
|
||||
ed25519: (seed) => utilCrypto.ed25519PairFromSeed(seed),
|
||||
ethereum: (seed) => utilCrypto.secp256k1PairFromSeed(seed),
|
||||
sr25519: (seed) => utilCrypto.sr25519PairFromSeed(seed)
|
||||
};
|
||||
function pairToPublic({ publicKey }) {
|
||||
return publicKey;
|
||||
}
|
||||
class Keyring {
|
||||
#pairs;
|
||||
#type;
|
||||
#ss58;
|
||||
decodeAddress = utilCrypto.decodeAddress;
|
||||
constructor(options = {}) {
|
||||
options.type = options.type || 'ed25519';
|
||||
if (!['ecdsa', 'ethereum', 'ed25519', 'sr25519'].includes(options.type || 'undefined')) {
|
||||
throw new Error(`Expected a keyring type of either 'ed25519', 'sr25519', 'ethereum' or 'ecdsa', found '${options.type || 'unknown'}`);
|
||||
}
|
||||
this.#pairs = new Pairs();
|
||||
this.#ss58 = options.ss58Format;
|
||||
this.#type = options.type;
|
||||
}
|
||||
get pairs() {
|
||||
return this.getPairs();
|
||||
}
|
||||
get publicKeys() {
|
||||
return this.getPublicKeys();
|
||||
}
|
||||
get type() {
|
||||
return this.#type;
|
||||
}
|
||||
addPair(pair) {
|
||||
return this.#pairs.add(pair);
|
||||
}
|
||||
addFromAddress(address, meta = {}, encoded = null, type = this.type, ignoreChecksum, encType) {
|
||||
const publicKey = this.decodeAddress(address, ignoreChecksum);
|
||||
return this.addPair(createPair({ toSS58: this.encodeAddress, type }, { publicKey, secretKey: new Uint8Array() }, meta, encoded, encType));
|
||||
}
|
||||
addFromJson(json, ignoreChecksum) {
|
||||
return this.addPair(this.createFromJson(json, ignoreChecksum));
|
||||
}
|
||||
addFromMnemonic(mnemonic, meta = {}, type = this.type, wordlist) {
|
||||
return this.addFromUri(mnemonic, meta, type, wordlist);
|
||||
}
|
||||
addFromPair(pair, meta = {}, type = this.type) {
|
||||
return this.addPair(this.createFromPair(pair, meta, type));
|
||||
}
|
||||
addFromSeed(seed, meta = {}, type = this.type) {
|
||||
return this.addPair(createPair({ toSS58: this.encodeAddress, type }, PairFromSeed[type](seed), meta, null));
|
||||
}
|
||||
addFromUri(suri, meta = {}, type = this.type, wordlist) {
|
||||
return this.addPair(this.createFromUri(suri, meta, type, wordlist));
|
||||
}
|
||||
createFromJson({ address, encoded, encoding: { content, type, version }, meta }, ignoreChecksum) {
|
||||
if (version === '3' && content[0] !== 'pkcs8') {
|
||||
throw new Error(`Unable to decode non-pkcs8 type, [${content.join(',')}] found}`);
|
||||
}
|
||||
const cryptoType = version === '0' || !Array.isArray(content)
|
||||
? this.type
|
||||
: content[1];
|
||||
const encType = !Array.isArray(type)
|
||||
? [type]
|
||||
: type;
|
||||
if (!['ed25519', 'sr25519', 'ecdsa', 'ethereum'].includes(cryptoType)) {
|
||||
throw new Error(`Unknown crypto type ${cryptoType}`);
|
||||
}
|
||||
const publicKey = util.isHex(address)
|
||||
? util.hexToU8a(address)
|
||||
: this.decodeAddress(address, ignoreChecksum);
|
||||
const decoded = util.isHex(encoded)
|
||||
? util.hexToU8a(encoded)
|
||||
: utilCrypto.base64Decode(encoded);
|
||||
return createPair({ toSS58: this.encodeAddress, type: cryptoType }, { publicKey, secretKey: new Uint8Array() }, meta, decoded, encType);
|
||||
}
|
||||
createFromPair(pair, meta = {}, type = this.type) {
|
||||
return createPair({ toSS58: this.encodeAddress, type }, pair, meta, null);
|
||||
}
|
||||
createFromUri(_suri, meta = {}, type = this.type, wordlist) {
|
||||
const suri = _suri.startsWith('//')
|
||||
? `${DEV_PHRASE}${_suri}`
|
||||
: _suri;
|
||||
const { derivePath, password, path, phrase } = utilCrypto.keyExtractSuri(suri);
|
||||
let seed;
|
||||
const isPhraseHex = util.isHex(phrase, 256);
|
||||
if (isPhraseHex) {
|
||||
seed = util.hexToU8a(phrase);
|
||||
}
|
||||
else {
|
||||
const parts = phrase.split(' ');
|
||||
if ([12, 15, 18, 21, 24].includes(parts.length)) {
|
||||
seed = type === 'ethereum'
|
||||
? utilCrypto.mnemonicToLegacySeed(phrase, '', false, 64)
|
||||
: utilCrypto.mnemonicToMiniSecret(phrase, password, wordlist);
|
||||
}
|
||||
else {
|
||||
if (phrase.length > 32) {
|
||||
throw new Error('specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes');
|
||||
}
|
||||
seed = util.stringToU8a(phrase.padEnd(32));
|
||||
}
|
||||
}
|
||||
const derived = type === 'ethereum'
|
||||
? isPhraseHex
|
||||
? PairFromSeed[type](seed)
|
||||
: utilCrypto.hdEthereum(seed, derivePath.substring(1))
|
||||
: utilCrypto.keyFromPath(PairFromSeed[type](seed), path, type);
|
||||
return createPair({ toSS58: this.encodeAddress, type }, derived, meta, null);
|
||||
}
|
||||
encodeAddress = (address, ss58Format) => {
|
||||
return this.type === 'ethereum'
|
||||
? utilCrypto.ethereumEncode(address)
|
||||
: utilCrypto.encodeAddress(address, ss58Format ?? this.#ss58);
|
||||
};
|
||||
getPair(address) {
|
||||
return this.#pairs.get(address);
|
||||
}
|
||||
getPairs() {
|
||||
return this.#pairs.all();
|
||||
}
|
||||
getPublicKeys() {
|
||||
return this.#pairs.all().map(pairToPublic);
|
||||
}
|
||||
removePair(address) {
|
||||
this.#pairs.remove(address);
|
||||
}
|
||||
setSS58Format(ss58) {
|
||||
this.#ss58 = ss58;
|
||||
}
|
||||
toJson(address, passphrase) {
|
||||
return this.#pairs.get(address).toJson(passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
const packageInfo = { name: '@pezkuwi/keyring', path: (({ url: (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bundle-pezkuwi-keyring.js', document.baseURI).href)) }) && (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bundle-pezkuwi-keyring.js', document.baseURI).href))) ? new URL((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bundle-pezkuwi-keyring.js', document.baseURI).href))).pathname.substring(0, new URL((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bundle-pezkuwi-keyring.js', document.baseURI).href))).pathname.lastIndexOf('/') + 1) : 'auto', type: 'esm', version: '14.0.10' };
|
||||
|
||||
const PAIRSSR25519 = [
|
||||
{
|
||||
p: '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
|
||||
s: '0x98319d4ff8a9508c4bb0cf0b5a78d760a0b2082c02775e6e82370816fedfff48925a225d97aa00682d6a59b95b18780c10d7032336e88f3442b42361f4a66011',
|
||||
seed: 'Alice',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f',
|
||||
s: '0xe8da6c9d810e020f5e3c7f5af2dea314cbeaa0d72bc6421e92c0808a0c584a6046ab28e97c3ffc77fe12b5a4d37e8cd4afbfebbf2391ffc7cb07c0f38c023efd',
|
||||
seed: 'Alice//stash',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48',
|
||||
s: '0x081ff694633e255136bdb456c20a5fc8fed21f8b964c11bb17ff534ce80ebd5941ae88f85d0c1bfc37be41c904e1dfc01de8c8067b0d6d5df25dd1ac0894a325',
|
||||
seed: 'Bob',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e',
|
||||
s: '0xc006507cdfc267a21532394c49ca9b754ca71de21e15a1cdf807c7ceab6d0b6c3ed408d9d35311540dcd54931933e67cf1ea10d46f75408f82b789d9bd212fde',
|
||||
seed: 'Bob//stash',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22',
|
||||
s: '0xa8f2d83016052e5d6d77b2f6fd5d59418922a09024cda701b3c34369ec43a7668faf12ff39cd4e5d92bb773972f41a7a5279ebc2ed92264bed8f47d344f8f18c',
|
||||
seed: 'Charlie',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0x306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20',
|
||||
s: '0x20e05482ca4677e0edbc58ae9a3a59f6ed3b1a9484ba17e64d6fe8688b2b7b5d108c4487b9323b98b11fe36cb301b084e920f7b7895536809a6d62a451b25568',
|
||||
seed: 'Dave',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0xe659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e',
|
||||
s: '0x683576abfd5dc35273e4264c23095a1bf21c14517bece57c7f0cc5c0ed4ce06a3dbf386b7828f348abe15d76973a72009e6ef86a5c91db2990cb36bb657c6587',
|
||||
seed: 'Eve',
|
||||
type: 'sr25519'
|
||||
},
|
||||
{
|
||||
p: '0x1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c',
|
||||
s: '0xb835c20f450079cf4f513900ae9faf8df06ad86c681884122c752a4b2bf74d4303e4f21bc6cc62bb4eeed5a9cce642c25e2d2ac1464093b50f6196d78e3a7426',
|
||||
seed: 'Ferdie',
|
||||
type: 'sr25519'
|
||||
}
|
||||
];
|
||||
const PAIRSETHEREUM = [
|
||||
{
|
||||
name: 'Alith',
|
||||
p: '0x02509540919faacf9ab52146c9aa40db68172d83777250b28e4679176e49ccdd9f',
|
||||
s: '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133',
|
||||
type: 'ethereum'
|
||||
},
|
||||
{
|
||||
name: 'Baltathar',
|
||||
p: '0x033bc19e36ff1673910575b6727a974a9abd80c9a875d41ab3e2648dbfb9e4b518',
|
||||
s: '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b',
|
||||
type: 'ethereum'
|
||||
},
|
||||
{
|
||||
name: 'Charleth',
|
||||
p: '0x0234637bdc0e89b5d46543bcbf8edff329d2702bc995e27e9af4b1ba009a3c2a5e',
|
||||
s: '0x0b6e18cafb6ed99687ec547bd28139cafdd2bffe70e6b688025de6b445aa5c5b',
|
||||
type: 'ethereum'
|
||||
},
|
||||
{
|
||||
name: 'Dorothy',
|
||||
p: '0x02a00d60b2b408c2a14c5d70cdd2c205db8985ef737a7e55ad20ea32cc9e7c417c',
|
||||
s: '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68',
|
||||
type: 'ethereum'
|
||||
},
|
||||
{
|
||||
name: 'Ethan',
|
||||
p: '0x025cdc005b752651cd3f728fb9192182acb3a9c89e19072cbd5b03f3ee1f1b3ffa',
|
||||
s: '0x7dce9bc8babb68fec1409be38c8e1a52650206a7ed90ff956ae8a6d15eeaaef4',
|
||||
type: 'ethereum'
|
||||
},
|
||||
{
|
||||
name: 'Faith',
|
||||
p: '0x037964b6c9d546da4646ada28a99e34acaa1d14e7aba861a9055f9bd200c8abf74',
|
||||
s: '0xb9d2ea9a615f3165812e8d44de0d24da9bbd164b65c4f0573e1ce2c8dbd9c8df',
|
||||
type: 'ethereum'
|
||||
}
|
||||
];
|
||||
function createMeta(name, seed) {
|
||||
if (!name && !seed) {
|
||||
throw new Error('Testing pair should have either a name or a seed');
|
||||
}
|
||||
return {
|
||||
isTesting: true,
|
||||
name: name || seed?.replace('//', '_').toLowerCase()
|
||||
};
|
||||
}
|
||||
function createTestKeyring(options = {}, isDerived = true) {
|
||||
const keyring = new Keyring(options);
|
||||
const pairs = options.type === 'ethereum'
|
||||
? PAIRSETHEREUM
|
||||
: PAIRSSR25519;
|
||||
for (const { name, p, s, seed, type } of pairs) {
|
||||
const meta = createMeta(name, seed);
|
||||
const pair = !isDerived && !name && seed
|
||||
? keyring.addFromUri(seed, meta, options.type)
|
||||
: keyring.addPair(createPair({ toSS58: keyring.encodeAddress, type }, { publicKey: util.hexToU8a(p), secretKey: util.hexToU8a(s) }, meta));
|
||||
pair.lock = () => {
|
||||
};
|
||||
}
|
||||
return keyring;
|
||||
}
|
||||
|
||||
const publicKey = new Uint8Array(32);
|
||||
const address = '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM';
|
||||
const meta = {
|
||||
isTesting: true,
|
||||
name: 'nobody'
|
||||
};
|
||||
const json = {
|
||||
address,
|
||||
encoded: '',
|
||||
encoding: {
|
||||
content: ['pkcs8', 'ed25519'],
|
||||
type: 'none',
|
||||
version: '0'
|
||||
},
|
||||
meta
|
||||
};
|
||||
const pair = {
|
||||
address,
|
||||
addressRaw: publicKey,
|
||||
decodePkcs8: (_passphrase, _encoded) => undefined,
|
||||
derive: (_suri, _meta) => pair,
|
||||
encodePkcs8: (_passphrase) => new Uint8Array(0),
|
||||
isLocked: true,
|
||||
lock: () => {
|
||||
},
|
||||
meta,
|
||||
publicKey,
|
||||
setMeta: (_meta) => undefined,
|
||||
sign: (_message) => new Uint8Array(64),
|
||||
toJson: (_passphrase) => json,
|
||||
type: 'ed25519',
|
||||
unlock: (_passphrase) => undefined,
|
||||
verify: (_message, _signature) => false,
|
||||
vrfSign: (_message, _context, _extra) => new Uint8Array(96),
|
||||
vrfVerify: (_message, _vrfResult, _context, _extra) => false
|
||||
};
|
||||
function nobody() {
|
||||
return pair;
|
||||
}
|
||||
|
||||
function createTestPairs(options, isDerived = true) {
|
||||
const keyring = createTestKeyring(options, isDerived);
|
||||
const pairs = keyring.getPairs();
|
||||
const map = { nobody: nobody() };
|
||||
for (const p of pairs) {
|
||||
if (p.meta.name) {
|
||||
map[p.meta.name] = p;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Object.defineProperty(exports, "decodeAddress", {
|
||||
enumerable: true,
|
||||
get: function () { return utilCrypto.decodeAddress; }
|
||||
});
|
||||
Object.defineProperty(exports, "encodeAddress", {
|
||||
enumerable: true,
|
||||
get: function () { return utilCrypto.encodeAddress; }
|
||||
});
|
||||
Object.defineProperty(exports, "setSS58Format", {
|
||||
enumerable: true,
|
||||
get: function () { return utilCrypto.setSS58Format; }
|
||||
});
|
||||
exports.DEV_PHRASE = DEV_PHRASE;
|
||||
exports.DEV_SEED = DEV_SEED;
|
||||
exports.Keyring = Keyring;
|
||||
exports.createPair = createPair;
|
||||
exports.createTestKeyring = createTestKeyring;
|
||||
exports.createTestPairs = createTestPairs;
|
||||
exports.packageInfo = packageInfo;
|
||||
|
||||
}));
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export { decodeAddress, encodeAddress, setSS58Format } from '@pezkuwi/util-crypto';
|
||||
export { Keyring } from './keyring.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export { createPair } from './pair/index.js';
|
||||
export { createTestKeyring } from './testing.js';
|
||||
export { createTestPairs } from './testingPairs.js';
|
||||
export * from './defaults.js';
|
||||
@@ -0,0 +1,7 @@
|
||||
export { decodeAddress, encodeAddress, setSS58Format } from '@pezkuwi/util-crypto';
|
||||
export { Keyring } from './keyring.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export { createPair } from './pair/index.js';
|
||||
export { createTestKeyring } from './testing.js';
|
||||
export { createTestPairs } from './testingPairs.js';
|
||||
export * from './defaults.js';
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export { decodeAddress, encodeAddress, setSS58Format } from '@pezkuwi/util-crypto';
|
||||
export { Keyring } from './keyring.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
export { createPair } from './pair/index.js';
|
||||
export { createTestKeyring } from './testing.js';
|
||||
export { createTestPairs } from './testingPairs.js';
|
||||
export * from './defaults.js';
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createTestPairs = exports.createTestKeyring = exports.createPair = exports.packageInfo = exports.Keyring = exports.setSS58Format = exports.encodeAddress = exports.decodeAddress = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
var util_crypto_1 = require("@pezkuwi/util-crypto");
|
||||
Object.defineProperty(exports, "decodeAddress", { enumerable: true, get: function () { return util_crypto_1.decodeAddress; } });
|
||||
Object.defineProperty(exports, "encodeAddress", { enumerable: true, get: function () { return util_crypto_1.encodeAddress; } });
|
||||
Object.defineProperty(exports, "setSS58Format", { enumerable: true, get: function () { return util_crypto_1.setSS58Format; } });
|
||||
var keyring_js_1 = require("./keyring.js");
|
||||
Object.defineProperty(exports, "Keyring", { enumerable: true, get: function () { return keyring_js_1.Keyring; } });
|
||||
var packageInfo_js_1 = require("./packageInfo.js");
|
||||
Object.defineProperty(exports, "packageInfo", { enumerable: true, get: function () { return packageInfo_js_1.packageInfo; } });
|
||||
var index_js_1 = require("./pair/index.js");
|
||||
Object.defineProperty(exports, "createPair", { enumerable: true, get: function () { return index_js_1.createPair; } });
|
||||
var testing_js_1 = require("./testing.js");
|
||||
Object.defineProperty(exports, "createTestKeyring", { enumerable: true, get: function () { return testing_js_1.createTestKeyring; } });
|
||||
var testingPairs_js_1 = require("./testingPairs.js");
|
||||
Object.defineProperty(exports, "createTestPairs", { enumerable: true, get: function () { return testingPairs_js_1.createTestPairs; } });
|
||||
tslib_1.__exportStar(require("./defaults.js"), exports);
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export declare const DEV_PHRASE = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
|
||||
export declare const DEV_SEED = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e";
|
||||
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DEV_SEED = exports.DEV_PHRASE = void 0;
|
||||
exports.DEV_PHRASE = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk';
|
||||
exports.DEV_SEED = '0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e';
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import './packageDetect.js';
|
||||
import { Keyring } from './bundle.js';
|
||||
export * from './bundle.js';
|
||||
export default Keyring;
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
require("./packageDetect.js");
|
||||
const bundle_js_1 = require("./bundle.js");
|
||||
tslib_1.__exportStar(require("./bundle.js"), exports);
|
||||
exports.default = bundle_js_1.Keyring;
|
||||
Vendored
+145
@@ -0,0 +1,145 @@
|
||||
import type { EncryptedJsonEncoding, Keypair, KeypairType } from '@pezkuwi/util-crypto/types';
|
||||
import type { KeyringInstance, KeyringOptions, KeyringPair, KeyringPair$Json, KeyringPair$Meta } from './types.js';
|
||||
import { decodeAddress } from '@pezkuwi/util-crypto';
|
||||
/**
|
||||
* # @pezkuwi/keyring
|
||||
*
|
||||
* ## Overview
|
||||
*
|
||||
* @name Keyring
|
||||
* @summary Keyring management of user accounts
|
||||
* @description Allows generation of keyring pairs from a variety of input combinations, such as
|
||||
* json object containing account address or public key, account metadata, and account encoded using
|
||||
* `addFromJson`, or by providing those values as arguments separately to `addFromAddress`,
|
||||
* or by providing the mnemonic (seed phrase) and account metadata as arguments to `addFromMnemonic`.
|
||||
* Stores the keyring pairs in a keyring pair dictionary. Removal of the keyring pairs from the keyring pair
|
||||
* dictionary is achieved using `removePair`. Retrieval of all the stored pairs via `getPairs` or perform
|
||||
* lookup of a pair for a given account address or public key using `getPair`. JSON metadata associated with
|
||||
* an account may be obtained using `toJson` accompanied by the account passphrase.
|
||||
*/
|
||||
export declare class Keyring implements KeyringInstance {
|
||||
#private;
|
||||
decodeAddress: typeof decodeAddress;
|
||||
constructor(options?: KeyringOptions);
|
||||
/**
|
||||
* @description retrieve the pairs (alias for getPairs)
|
||||
*/
|
||||
get pairs(): KeyringPair[];
|
||||
/**
|
||||
* @description retrieve the publicKeys (alias for getPublicKeys)
|
||||
*/
|
||||
get publicKeys(): Uint8Array[];
|
||||
/**
|
||||
* @description Returns the type of the keyring, ed25519, sr25519 or ecdsa
|
||||
*/
|
||||
get type(): KeypairType;
|
||||
/**
|
||||
* @name addPair
|
||||
* @summary Stores an account, given a keyring pair, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
*/
|
||||
addPair(pair: KeyringPair): KeyringPair;
|
||||
/**
|
||||
* @name addFromAddress
|
||||
* @summary Stores an account, given an account address, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to explicitly provide separate inputs including account address or public key, and optionally
|
||||
* the associated account metadata, and the default encoded value as arguments (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from them that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromAddress(address: string | Uint8Array, meta?: KeyringPair$Meta, encoded?: Uint8Array | null, type?: KeypairType, ignoreChecksum?: boolean, encType?: EncryptedJsonEncoding[]): KeyringPair;
|
||||
/**
|
||||
* @name addFromJson
|
||||
* @summary Stores an account, given JSON data, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to provide a json object argument that contains account information (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromJson(json: KeyringPair$Json, ignoreChecksum?: boolean): KeyringPair;
|
||||
/**
|
||||
* @name addFromMnemonic
|
||||
* @summary Stores an account, given a mnemonic, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to provide a mnemonic (seed phrase that is provided when account is originally created)
|
||||
* argument and a metadata argument that contains account information (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromMnemonic(mnemonic: string, meta?: KeyringPair$Meta, type?: KeypairType, wordlist?: string[]): KeyringPair;
|
||||
/**
|
||||
* @name addFromPair
|
||||
* @summary Stores an account created from an explicit publicKey/secreteKey combination
|
||||
*/
|
||||
addFromPair(pair: Keypair, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair;
|
||||
/**
|
||||
* @name addFromSeed
|
||||
* @summary Stores an account, given seed data, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Stores in a keyring pair dictionary the public key of the pair as a key and the pair as the associated value.
|
||||
* Allows user to provide the account seed as an argument, and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to store in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromSeed(seed: Uint8Array, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair;
|
||||
/**
|
||||
* @name addFromUri
|
||||
* @summary Creates an account via an suri
|
||||
* @description Extracts the phrase, path and password from a SURI format for specifying secret keys `<secret>/<soft-key>//<hard-key>///<password>` (the `///password` may be omitted, and `/<soft-key>` and `//<hard-key>` maybe repeated and mixed). The secret can be a hex string, mnemonic phrase or a string (to be padded)
|
||||
*/
|
||||
addFromUri(suri: string, meta?: KeyringPair$Meta, type?: KeypairType, wordlist?: string[]): KeyringPair;
|
||||
/**
|
||||
* @name createFromJson
|
||||
* @description Creates a pair from a JSON keyfile
|
||||
*/
|
||||
createFromJson({ address, encoded, encoding: { content, type, version }, meta }: KeyringPair$Json, ignoreChecksum?: boolean): KeyringPair;
|
||||
/**
|
||||
* @name createFromPair
|
||||
* @summary Creates a pair from an explicit publicKey/secreteKey combination
|
||||
*/
|
||||
createFromPair(pair: Keypair, meta?: KeyringPair$Meta, type?: KeypairType): KeyringPair;
|
||||
/**
|
||||
* @name createFromUri
|
||||
* @summary Creates a Keypair from an suri
|
||||
* @description This creates a pair from the suri, but does not add it to the keyring
|
||||
*/
|
||||
createFromUri(_suri: string, meta?: KeyringPair$Meta, type?: KeypairType, wordlist?: string[]): KeyringPair;
|
||||
/**
|
||||
* @name encodeAddress
|
||||
* @description Encodes the input into an ss58 representation
|
||||
*/
|
||||
encodeAddress: (address: Uint8Array | string, ss58Format?: number) => string;
|
||||
/**
|
||||
* @name getPair
|
||||
* @summary Retrieves an account keyring pair from the Keyring Pair Dictionary, given an account address
|
||||
* @description Returns a keyring pair value from the keyring pair dictionary by performing
|
||||
* a key lookup using the provided account address or public key (after decoding it).
|
||||
*/
|
||||
getPair(address: string | Uint8Array): KeyringPair;
|
||||
/**
|
||||
* @name getPairs
|
||||
* @summary Retrieves all account keyring pairs from the Keyring Pair Dictionary
|
||||
* @description Returns an array list of all the keyring pair values that are stored in the keyring pair dictionary.
|
||||
*/
|
||||
getPairs(): KeyringPair[];
|
||||
/**
|
||||
* @name getPublicKeys
|
||||
* @summary Retrieves Public Keys of all Keyring Pairs stored in the Keyring Pair Dictionary
|
||||
* @description Returns an array list of all the public keys associated with each of the keyring pair values that are stored in the keyring pair dictionary.
|
||||
*/
|
||||
getPublicKeys(): Uint8Array[];
|
||||
/**
|
||||
* @name removePair
|
||||
* @description Deletes the provided input address or public key from the stored Keyring Pair Dictionary.
|
||||
*/
|
||||
removePair(address: string | Uint8Array): void;
|
||||
/**
|
||||
* @name setSS58Format;
|
||||
* @description Sets the ss58 format for the keyring
|
||||
*/
|
||||
setSS58Format(ss58: number): void;
|
||||
/**
|
||||
* @name toJson
|
||||
* @summary Returns a JSON object associated with the input argument that contains metadata assocated with an account
|
||||
* @description Returns a JSON object containing the metadata associated with an account
|
||||
* when valid address or public key and when the account passphrase is provided if the account secret
|
||||
* is not already unlocked and available in memory. Note that in [Polkadot-JS Apps](https://github.com/polkadot-js/apps) the user
|
||||
* may backup their account to a JSON file that contains this information.
|
||||
*/
|
||||
toJson(address: string | Uint8Array, passphrase?: string): KeyringPair$Json;
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Keyring = void 0;
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const util_crypto_1 = require("@pezkuwi/util-crypto");
|
||||
const index_js_1 = require("./pair/index.js");
|
||||
const defaults_js_1 = require("./defaults.js");
|
||||
const pairs_js_1 = require("./pairs.js");
|
||||
const PairFromSeed = {
|
||||
ecdsa: (seed) => (0, util_crypto_1.secp256k1PairFromSeed)(seed),
|
||||
ed25519: (seed) => (0, util_crypto_1.ed25519PairFromSeed)(seed),
|
||||
ethereum: (seed) => (0, util_crypto_1.secp256k1PairFromSeed)(seed),
|
||||
sr25519: (seed) => (0, util_crypto_1.sr25519PairFromSeed)(seed)
|
||||
};
|
||||
function pairToPublic({ publicKey }) {
|
||||
return publicKey;
|
||||
}
|
||||
/**
|
||||
* # @pezkuwi/keyring
|
||||
*
|
||||
* ## Overview
|
||||
*
|
||||
* @name Keyring
|
||||
* @summary Keyring management of user accounts
|
||||
* @description Allows generation of keyring pairs from a variety of input combinations, such as
|
||||
* json object containing account address or public key, account metadata, and account encoded using
|
||||
* `addFromJson`, or by providing those values as arguments separately to `addFromAddress`,
|
||||
* or by providing the mnemonic (seed phrase) and account metadata as arguments to `addFromMnemonic`.
|
||||
* Stores the keyring pairs in a keyring pair dictionary. Removal of the keyring pairs from the keyring pair
|
||||
* dictionary is achieved using `removePair`. Retrieval of all the stored pairs via `getPairs` or perform
|
||||
* lookup of a pair for a given account address or public key using `getPair`. JSON metadata associated with
|
||||
* an account may be obtained using `toJson` accompanied by the account passphrase.
|
||||
*/
|
||||
class Keyring {
|
||||
#pairs;
|
||||
#type;
|
||||
#ss58;
|
||||
decodeAddress = util_crypto_1.decodeAddress;
|
||||
constructor(options = {}) {
|
||||
options.type = options.type || 'ed25519';
|
||||
if (!['ecdsa', 'ethereum', 'ed25519', 'sr25519'].includes(options.type || 'undefined')) {
|
||||
throw new Error(`Expected a keyring type of either 'ed25519', 'sr25519', 'ethereum' or 'ecdsa', found '${options.type || 'unknown'}`);
|
||||
}
|
||||
this.#pairs = new pairs_js_1.Pairs();
|
||||
this.#ss58 = options.ss58Format;
|
||||
this.#type = options.type;
|
||||
}
|
||||
/**
|
||||
* @description retrieve the pairs (alias for getPairs)
|
||||
*/
|
||||
get pairs() {
|
||||
return this.getPairs();
|
||||
}
|
||||
/**
|
||||
* @description retrieve the publicKeys (alias for getPublicKeys)
|
||||
*/
|
||||
get publicKeys() {
|
||||
return this.getPublicKeys();
|
||||
}
|
||||
/**
|
||||
* @description Returns the type of the keyring, ed25519, sr25519 or ecdsa
|
||||
*/
|
||||
get type() {
|
||||
return this.#type;
|
||||
}
|
||||
/**
|
||||
* @name addPair
|
||||
* @summary Stores an account, given a keyring pair, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
*/
|
||||
addPair(pair) {
|
||||
return this.#pairs.add(pair);
|
||||
}
|
||||
/**
|
||||
* @name addFromAddress
|
||||
* @summary Stores an account, given an account address, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to explicitly provide separate inputs including account address or public key, and optionally
|
||||
* the associated account metadata, and the default encoded value as arguments (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from them that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromAddress(address, meta = {}, encoded = null, type = this.type, ignoreChecksum, encType) {
|
||||
const publicKey = this.decodeAddress(address, ignoreChecksum);
|
||||
return this.addPair((0, index_js_1.createPair)({ toSS58: this.encodeAddress, type }, { publicKey, secretKey: new Uint8Array() }, meta, encoded, encType));
|
||||
}
|
||||
/**
|
||||
* @name addFromJson
|
||||
* @summary Stores an account, given JSON data, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to provide a json object argument that contains account information (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromJson(json, ignoreChecksum) {
|
||||
return this.addPair(this.createFromJson(json, ignoreChecksum));
|
||||
}
|
||||
/**
|
||||
* @name addFromMnemonic
|
||||
* @summary Stores an account, given a mnemonic, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Allows user to provide a mnemonic (seed phrase that is provided when account is originally created)
|
||||
* argument and a metadata argument that contains account information (that may be obtained from the json file
|
||||
* of an account backup), and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to stores in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromMnemonic(mnemonic, meta = {}, type = this.type, wordlist) {
|
||||
return this.addFromUri(mnemonic, meta, type, wordlist);
|
||||
}
|
||||
/**
|
||||
* @name addFromPair
|
||||
* @summary Stores an account created from an explicit publicKey/secreteKey combination
|
||||
*/
|
||||
addFromPair(pair, meta = {}, type = this.type) {
|
||||
return this.addPair(this.createFromPair(pair, meta, type));
|
||||
}
|
||||
/**
|
||||
* @name addFromSeed
|
||||
* @summary Stores an account, given seed data, as a Key/Value (public key, pair) in Keyring Pair Dictionary
|
||||
* @description Stores in a keyring pair dictionary the public key of the pair as a key and the pair as the associated value.
|
||||
* Allows user to provide the account seed as an argument, and then generates a keyring pair from it that it passes to
|
||||
* `addPair` to store in a keyring pair dictionary the public key of the generated pair as a key and the pair as the associated value.
|
||||
*/
|
||||
addFromSeed(seed, meta = {}, type = this.type) {
|
||||
return this.addPair((0, index_js_1.createPair)({ toSS58: this.encodeAddress, type }, PairFromSeed[type](seed), meta, null));
|
||||
}
|
||||
/**
|
||||
* @name addFromUri
|
||||
* @summary Creates an account via an suri
|
||||
* @description Extracts the phrase, path and password from a SURI format for specifying secret keys `<secret>/<soft-key>//<hard-key>///<password>` (the `///password` may be omitted, and `/<soft-key>` and `//<hard-key>` maybe repeated and mixed). The secret can be a hex string, mnemonic phrase or a string (to be padded)
|
||||
*/
|
||||
addFromUri(suri, meta = {}, type = this.type, wordlist) {
|
||||
return this.addPair(this.createFromUri(suri, meta, type, wordlist));
|
||||
}
|
||||
/**
|
||||
* @name createFromJson
|
||||
* @description Creates a pair from a JSON keyfile
|
||||
*/
|
||||
createFromJson({ address, encoded, encoding: { content, type, version }, meta }, ignoreChecksum) {
|
||||
if (version === '3' && content[0] !== 'pkcs8') {
|
||||
throw new Error(`Unable to decode non-pkcs8 type, [${content.join(',')}] found}`);
|
||||
}
|
||||
const cryptoType = version === '0' || !Array.isArray(content)
|
||||
? this.type
|
||||
: content[1];
|
||||
const encType = !Array.isArray(type)
|
||||
? [type]
|
||||
: type;
|
||||
if (!['ed25519', 'sr25519', 'ecdsa', 'ethereum'].includes(cryptoType)) {
|
||||
throw new Error(`Unknown crypto type ${cryptoType}`);
|
||||
}
|
||||
// Here the address and publicKey are 32 bytes and isomorphic. This is why the address field needs to be the public key for ethereum type pairs
|
||||
const publicKey = (0, util_1.isHex)(address)
|
||||
? (0, util_1.hexToU8a)(address)
|
||||
: this.decodeAddress(address, ignoreChecksum);
|
||||
const decoded = (0, util_1.isHex)(encoded)
|
||||
? (0, util_1.hexToU8a)(encoded)
|
||||
: (0, util_crypto_1.base64Decode)(encoded);
|
||||
return (0, index_js_1.createPair)({ toSS58: this.encodeAddress, type: cryptoType }, { publicKey, secretKey: new Uint8Array() }, meta, decoded, encType);
|
||||
}
|
||||
/**
|
||||
* @name createFromPair
|
||||
* @summary Creates a pair from an explicit publicKey/secreteKey combination
|
||||
*/
|
||||
createFromPair(pair, meta = {}, type = this.type) {
|
||||
return (0, index_js_1.createPair)({ toSS58: this.encodeAddress, type }, pair, meta, null);
|
||||
}
|
||||
/**
|
||||
* @name createFromUri
|
||||
* @summary Creates a Keypair from an suri
|
||||
* @description This creates a pair from the suri, but does not add it to the keyring
|
||||
*/
|
||||
createFromUri(_suri, meta = {}, type = this.type, wordlist) {
|
||||
// here we only aut-add the dev phrase if we have a hard-derived path
|
||||
const suri = _suri.startsWith('//')
|
||||
? `${defaults_js_1.DEV_PHRASE}${_suri}`
|
||||
: _suri;
|
||||
const { derivePath, password, path, phrase } = (0, util_crypto_1.keyExtractSuri)(suri);
|
||||
let seed;
|
||||
const isPhraseHex = (0, util_1.isHex)(phrase, 256);
|
||||
if (isPhraseHex) {
|
||||
seed = (0, util_1.hexToU8a)(phrase);
|
||||
}
|
||||
else {
|
||||
const parts = phrase.split(' ');
|
||||
if ([12, 15, 18, 21, 24].includes(parts.length)) {
|
||||
seed = type === 'ethereum'
|
||||
? (0, util_crypto_1.mnemonicToLegacySeed)(phrase, '', false, 64)
|
||||
: (0, util_crypto_1.mnemonicToMiniSecret)(phrase, password, wordlist);
|
||||
}
|
||||
else {
|
||||
if (phrase.length > 32) {
|
||||
throw new Error('specified phrase is not a valid mnemonic and is invalid as a raw seed at > 32 bytes');
|
||||
}
|
||||
seed = (0, util_1.stringToU8a)(phrase.padEnd(32));
|
||||
}
|
||||
}
|
||||
const derived = type === 'ethereum'
|
||||
? isPhraseHex
|
||||
? PairFromSeed[type](seed) // for eth, if the private key is provided as suri, it must be derived only once
|
||||
: (0, util_crypto_1.hdEthereum)(seed, derivePath.substring(1))
|
||||
: (0, util_crypto_1.keyFromPath)(PairFromSeed[type](seed), path, type);
|
||||
return (0, index_js_1.createPair)({ toSS58: this.encodeAddress, type }, derived, meta, null);
|
||||
}
|
||||
/**
|
||||
* @name encodeAddress
|
||||
* @description Encodes the input into an ss58 representation
|
||||
*/
|
||||
encodeAddress = (address, ss58Format) => {
|
||||
return this.type === 'ethereum'
|
||||
? (0, util_crypto_1.ethereumEncode)(address)
|
||||
: (0, util_crypto_1.encodeAddress)(address, ss58Format ?? this.#ss58);
|
||||
};
|
||||
/**
|
||||
* @name getPair
|
||||
* @summary Retrieves an account keyring pair from the Keyring Pair Dictionary, given an account address
|
||||
* @description Returns a keyring pair value from the keyring pair dictionary by performing
|
||||
* a key lookup using the provided account address or public key (after decoding it).
|
||||
*/
|
||||
getPair(address) {
|
||||
return this.#pairs.get(address);
|
||||
}
|
||||
/**
|
||||
* @name getPairs
|
||||
* @summary Retrieves all account keyring pairs from the Keyring Pair Dictionary
|
||||
* @description Returns an array list of all the keyring pair values that are stored in the keyring pair dictionary.
|
||||
*/
|
||||
getPairs() {
|
||||
return this.#pairs.all();
|
||||
}
|
||||
/**
|
||||
* @name getPublicKeys
|
||||
* @summary Retrieves Public Keys of all Keyring Pairs stored in the Keyring Pair Dictionary
|
||||
* @description Returns an array list of all the public keys associated with each of the keyring pair values that are stored in the keyring pair dictionary.
|
||||
*/
|
||||
getPublicKeys() {
|
||||
return this.#pairs.all().map(pairToPublic);
|
||||
}
|
||||
/**
|
||||
* @name removePair
|
||||
* @description Deletes the provided input address or public key from the stored Keyring Pair Dictionary.
|
||||
*/
|
||||
removePair(address) {
|
||||
this.#pairs.remove(address);
|
||||
}
|
||||
/**
|
||||
* @name setSS58Format;
|
||||
* @description Sets the ss58 format for the keyring
|
||||
*/
|
||||
setSS58Format(ss58) {
|
||||
this.#ss58 = ss58;
|
||||
}
|
||||
/**
|
||||
* @name toJson
|
||||
* @summary Returns a JSON object associated with the input argument that contains metadata assocated with an account
|
||||
* @description Returns a JSON object containing the metadata associated with an account
|
||||
* when valid address or public key and when the account passphrase is provided if the account secret
|
||||
* is not already unlocked and available in memory. Note that in [Polkadot-JS Apps](https://github.com/polkadot-js/apps) the user
|
||||
* may backup their account to a JSON file that contains this information.
|
||||
*/
|
||||
toJson(address, passphrase) {
|
||||
return this.#pairs.get(address).toJson(passphrase);
|
||||
}
|
||||
}
|
||||
exports.Keyring = Keyring;
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const packageInfo_1 = require("@pezkuwi/util/cjs/packageInfo");
|
||||
const packageInfo_2 = require("@pezkuwi/util-crypto/cjs/packageInfo");
|
||||
const packageInfo_js_1 = require("./packageInfo.js");
|
||||
(0, util_1.detectPackage)(packageInfo_js_1.packageInfo, null, [packageInfo_2.packageInfo, packageInfo_1.packageInfo]);
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export declare const packageInfo: {
|
||||
name: string;
|
||||
path: string;
|
||||
type: string;
|
||||
version: string;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.packageInfo = void 0;
|
||||
exports.packageInfo = { name: '@pezkuwi/keyring', path: typeof __dirname === 'string' ? __dirname : 'auto', type: 'cjs', version: '14.0.10' };
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import type { EncryptedJsonEncoding } from '@pezkuwi/util-crypto/types';
|
||||
/**
|
||||
* Decode a pair, taking into account the generation-specific formats and headers
|
||||
*
|
||||
* For divisor/headers, don't rely on the magic being static. These will
|
||||
* change between generations, aka with the long-awaited 4th generation
|
||||
* of the format. The external decode interface is the only way to use and decode these.
|
||||
**/
|
||||
export declare function decodePair(passphrase?: string, encrypted?: Uint8Array | null, _encType?: EncryptedJsonEncoding | EncryptedJsonEncoding[]): {
|
||||
publicKey: Uint8Array;
|
||||
secretKey: Uint8Array;
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.decodePair = decodePair;
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const util_crypto_1 = require("@pezkuwi/util-crypto");
|
||||
const defaults_js_1 = require("./defaults.js");
|
||||
const SEED_OFFSET = defaults_js_1.PAIR_HDR.length;
|
||||
/**
|
||||
* Decode a pair, taking into account the generation-specific formats and headers
|
||||
*
|
||||
* For divisor/headers, don't rely on the magic being static. These will
|
||||
* change between generations, aka with the long-awaited 4th generation
|
||||
* of the format. The external decode interface is the only way to use and decode these.
|
||||
**/
|
||||
function decodePair(passphrase, encrypted, _encType) {
|
||||
const encType = Array.isArray(_encType) || _encType === undefined
|
||||
? _encType
|
||||
: [_encType];
|
||||
const decrypted = (0, util_crypto_1.jsonDecryptData)(encrypted, passphrase, encType);
|
||||
const header = decrypted.subarray(0, defaults_js_1.PAIR_HDR.length);
|
||||
// check the start header (generations 1-3)
|
||||
if (!(0, util_1.u8aEq)(header, defaults_js_1.PAIR_HDR)) {
|
||||
throw new Error('Invalid encoding header found in body');
|
||||
}
|
||||
// setup for generation 3 format
|
||||
let secretKey = decrypted.subarray(SEED_OFFSET, SEED_OFFSET + defaults_js_1.SEC_LENGTH);
|
||||
let divOffset = SEED_OFFSET + defaults_js_1.SEC_LENGTH;
|
||||
let divider = decrypted.subarray(divOffset, divOffset + defaults_js_1.PAIR_DIV.length);
|
||||
// old-style (generation 1 & 2), we have the seed here
|
||||
if (!(0, util_1.u8aEq)(divider, defaults_js_1.PAIR_DIV)) {
|
||||
divOffset = SEED_OFFSET + defaults_js_1.SEED_LENGTH;
|
||||
secretKey = decrypted.subarray(SEED_OFFSET, divOffset);
|
||||
divider = decrypted.subarray(divOffset, divOffset + defaults_js_1.PAIR_DIV.length);
|
||||
// check the divisior at this point (already checked for generation 3)
|
||||
if (!(0, util_1.u8aEq)(divider, defaults_js_1.PAIR_DIV)) {
|
||||
throw new Error('Invalid encoding divider found in body');
|
||||
}
|
||||
}
|
||||
const pubOffset = divOffset + defaults_js_1.PAIR_DIV.length;
|
||||
const publicKey = decrypted.subarray(pubOffset, pubOffset + defaults_js_1.PUB_LENGTH);
|
||||
return {
|
||||
publicKey,
|
||||
secretKey
|
||||
};
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/** public/secret section divider (generation 1-3, will change in 4, don't rely on value) */
|
||||
export declare const PAIR_DIV: Uint8Array;
|
||||
/** public/secret start block (generation 1-3, will change in 4, don't rely on value) */
|
||||
export declare const PAIR_HDR: Uint8Array;
|
||||
/** length of a public key */
|
||||
export declare const PUB_LENGTH = 32;
|
||||
/** length of a salt */
|
||||
export declare const SALT_LENGTH = 32;
|
||||
/** length of a secret key */
|
||||
export declare const SEC_LENGTH = 64;
|
||||
/** length of a user-input seed */
|
||||
export declare const SEED_LENGTH = 32;
|
||||
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SEED_LENGTH = exports.SEC_LENGTH = exports.SALT_LENGTH = exports.PUB_LENGTH = exports.PAIR_HDR = exports.PAIR_DIV = void 0;
|
||||
/** public/secret section divider (generation 1-3, will change in 4, don't rely on value) */
|
||||
exports.PAIR_DIV = new Uint8Array([161, 35, 3, 33, 0]);
|
||||
/** public/secret start block (generation 1-3, will change in 4, don't rely on value) */
|
||||
exports.PAIR_HDR = new Uint8Array([48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32]);
|
||||
/** length of a public key */
|
||||
exports.PUB_LENGTH = 32;
|
||||
/** length of a salt */
|
||||
exports.SALT_LENGTH = 32;
|
||||
/** length of a secret key */
|
||||
exports.SEC_LENGTH = 64;
|
||||
/** length of a user-input seed */
|
||||
exports.SEED_LENGTH = 32;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import type { PairInfo } from './types.js';
|
||||
/**
|
||||
* Encode a pair with the latest generation format (generation 3)
|
||||
**/
|
||||
export declare function encodePair({ publicKey, secretKey }: PairInfo, passphrase?: string): Uint8Array;
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodePair = encodePair;
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const util_crypto_1 = require("@pezkuwi/util-crypto");
|
||||
const defaults_js_1 = require("./defaults.js");
|
||||
/**
|
||||
* Encode a pair with the latest generation format (generation 3)
|
||||
**/
|
||||
function encodePair({ publicKey, secretKey }, passphrase) {
|
||||
if (!secretKey) {
|
||||
throw new Error('Expected a valid secretKey to be passed to encode');
|
||||
}
|
||||
const encoded = (0, util_1.u8aConcat)(defaults_js_1.PAIR_HDR, secretKey, defaults_js_1.PAIR_DIV, publicKey);
|
||||
if (!passphrase) {
|
||||
return encoded;
|
||||
}
|
||||
// this is only for generation 3 (previous generations are only handled in decoding)
|
||||
const { params, password, salt } = (0, util_crypto_1.scryptEncode)(passphrase);
|
||||
const { encrypted, nonce } = (0, util_crypto_1.naclEncrypt)(encoded, password.subarray(0, 32));
|
||||
return (0, util_1.u8aConcat)((0, util_crypto_1.scryptToU8a)(salt, params), nonce, encrypted);
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
import type { EncryptedJsonEncoding, KeypairType } from '@pezkuwi/util-crypto/types';
|
||||
import type { KeyringPair, KeyringPair$Meta } from '../types.js';
|
||||
import type { PairInfo } from './types.js';
|
||||
interface Setup {
|
||||
toSS58: (publicKey: Uint8Array) => string;
|
||||
type: KeypairType;
|
||||
}
|
||||
/**
|
||||
* @name createPair
|
||||
* @summary Creates a keyring pair object
|
||||
* @description Creates a keyring pair object with provided account public key, metadata, and encoded arguments.
|
||||
* The keyring pair stores the account state including the encoded address and associated metadata.
|
||||
*
|
||||
* It has properties whose values are functions that may be called to perform account actions:
|
||||
*
|
||||
* - `address` function retrieves the address associated with the account.
|
||||
* - `decodedPkcs8` function is called with the account passphrase and account encoded public key.
|
||||
* It decodes the encoded public key using the passphrase provided to obtain the decoded account public key
|
||||
* and associated secret key that are then available in memory, and changes the account address stored in the
|
||||
* state of the pair to correspond to the address of the decoded public key.
|
||||
* - `encodePkcs8` function when provided with the correct passphrase associated with the account pair
|
||||
* and when the secret key is in memory (when the account pair is not locked) it returns an encoded
|
||||
* public key of the account.
|
||||
* - `meta` is the metadata that is stored in the state of the pair, either when it was originally
|
||||
* created or set via `setMeta`.
|
||||
* - `publicKey` returns the public key stored in memory for the pair.
|
||||
* - `sign` may be used to return a signature by signing a provided message with the secret
|
||||
* key (if it is in memory) using Nacl.
|
||||
* - `toJson` calls another `toJson` function and provides the state of the pair,
|
||||
* it generates arguments to be passed to the other `toJson` function including an encoded public key of the account
|
||||
* that it generates using the secret key from memory (if it has been made available in memory)
|
||||
* and the optionally provided passphrase argument. It passes a third boolean argument to `toJson`
|
||||
* indicating whether the public key has been encoded or not (if a passphrase argument was provided then it is encoded).
|
||||
* The `toJson` function that it calls returns a JSON object with properties including the `address`
|
||||
* and `meta` that are assigned with the values stored in the corresponding state variables of the account pair,
|
||||
* an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding`
|
||||
* property that indicates whether the public key value of the `encoded` property is encoded or not.
|
||||
*/
|
||||
export declare function createPair({ toSS58, type }: Setup, { publicKey, secretKey }: PairInfo, meta?: KeyringPair$Meta, encoded?: Uint8Array | null, encTypes?: EncryptedJsonEncoding[]): KeyringPair;
|
||||
export {};
|
||||
@@ -0,0 +1,183 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPair = createPair;
|
||||
const util_1 = require("@pezkuwi/util");
|
||||
const util_crypto_1 = require("@pezkuwi/util-crypto");
|
||||
const decode_js_1 = require("./decode.js");
|
||||
const encode_js_1 = require("./encode.js");
|
||||
const toJson_js_1 = require("./toJson.js");
|
||||
const SIG_TYPE_NONE = new Uint8Array();
|
||||
const TYPE_FROM_SEED = {
|
||||
ecdsa: util_crypto_1.secp256k1PairFromSeed,
|
||||
ed25519: util_crypto_1.ed25519PairFromSeed,
|
||||
ethereum: util_crypto_1.secp256k1PairFromSeed,
|
||||
sr25519: util_crypto_1.sr25519PairFromSeed
|
||||
};
|
||||
const TYPE_PREFIX = {
|
||||
ecdsa: new Uint8Array([2]),
|
||||
ed25519: new Uint8Array([0]),
|
||||
ethereum: new Uint8Array([2]),
|
||||
sr25519: new Uint8Array([1])
|
||||
};
|
||||
const TYPE_SIGNATURE = {
|
||||
ecdsa: (m, p) => (0, util_crypto_1.secp256k1Sign)(m, p, 'blake2'),
|
||||
ed25519: util_crypto_1.ed25519Sign,
|
||||
ethereum: (m, p) => (0, util_crypto_1.secp256k1Sign)(m, p, 'keccak'),
|
||||
sr25519: util_crypto_1.sr25519Sign
|
||||
};
|
||||
const TYPE_ADDRESS = {
|
||||
ecdsa: (p) => p.length > 32 ? (0, util_crypto_1.blake2AsU8a)(p) : p,
|
||||
ed25519: (p) => p,
|
||||
ethereum: (p) => p.length === 20 ? p : (0, util_crypto_1.keccakAsU8a)((0, util_crypto_1.secp256k1Expand)(p)),
|
||||
sr25519: (p) => p
|
||||
};
|
||||
function isLocked(secretKey) {
|
||||
return !secretKey || (0, util_1.u8aEmpty)(secretKey);
|
||||
}
|
||||
function vrfHash(proof, context, extra) {
|
||||
return (0, util_crypto_1.blake2AsU8a)((0, util_1.u8aConcat)(context || '', extra || '', proof));
|
||||
}
|
||||
/**
|
||||
* @name createPair
|
||||
* @summary Creates a keyring pair object
|
||||
* @description Creates a keyring pair object with provided account public key, metadata, and encoded arguments.
|
||||
* The keyring pair stores the account state including the encoded address and associated metadata.
|
||||
*
|
||||
* It has properties whose values are functions that may be called to perform account actions:
|
||||
*
|
||||
* - `address` function retrieves the address associated with the account.
|
||||
* - `decodedPkcs8` function is called with the account passphrase and account encoded public key.
|
||||
* It decodes the encoded public key using the passphrase provided to obtain the decoded account public key
|
||||
* and associated secret key that are then available in memory, and changes the account address stored in the
|
||||
* state of the pair to correspond to the address of the decoded public key.
|
||||
* - `encodePkcs8` function when provided with the correct passphrase associated with the account pair
|
||||
* and when the secret key is in memory (when the account pair is not locked) it returns an encoded
|
||||
* public key of the account.
|
||||
* - `meta` is the metadata that is stored in the state of the pair, either when it was originally
|
||||
* created or set via `setMeta`.
|
||||
* - `publicKey` returns the public key stored in memory for the pair.
|
||||
* - `sign` may be used to return a signature by signing a provided message with the secret
|
||||
* key (if it is in memory) using Nacl.
|
||||
* - `toJson` calls another `toJson` function and provides the state of the pair,
|
||||
* it generates arguments to be passed to the other `toJson` function including an encoded public key of the account
|
||||
* that it generates using the secret key from memory (if it has been made available in memory)
|
||||
* and the optionally provided passphrase argument. It passes a third boolean argument to `toJson`
|
||||
* indicating whether the public key has been encoded or not (if a passphrase argument was provided then it is encoded).
|
||||
* The `toJson` function that it calls returns a JSON object with properties including the `address`
|
||||
* and `meta` that are assigned with the values stored in the corresponding state variables of the account pair,
|
||||
* an `encoded` property that is assigned with the encoded public key in hex format, and an `encoding`
|
||||
* property that indicates whether the public key value of the `encoded` property is encoded or not.
|
||||
*/
|
||||
function createPair({ toSS58, type }, { publicKey, secretKey }, meta = {}, encoded = null, encTypes) {
|
||||
const decodePkcs8 = (passphrase, userEncoded) => {
|
||||
const decoded = (0, decode_js_1.decodePair)(passphrase, userEncoded || encoded, encTypes);
|
||||
if (decoded.secretKey.length === 64) {
|
||||
publicKey = decoded.publicKey;
|
||||
secretKey = decoded.secretKey;
|
||||
}
|
||||
else {
|
||||
const pair = TYPE_FROM_SEED[type](decoded.secretKey);
|
||||
publicKey = pair.publicKey;
|
||||
secretKey = pair.secretKey;
|
||||
}
|
||||
};
|
||||
const recode = (passphrase) => {
|
||||
isLocked(secretKey) && encoded && decodePkcs8(passphrase, encoded);
|
||||
encoded = (0, encode_js_1.encodePair)({ publicKey, secretKey }, passphrase); // re-encode, latest version
|
||||
encTypes = undefined; // swap to defaults, latest version follows
|
||||
return encoded;
|
||||
};
|
||||
const encodeAddress = () => {
|
||||
const raw = TYPE_ADDRESS[type](publicKey);
|
||||
return type === 'ethereum'
|
||||
? (0, util_crypto_1.ethereumEncode)(raw)
|
||||
: toSS58(raw);
|
||||
};
|
||||
return {
|
||||
get address() {
|
||||
return encodeAddress();
|
||||
},
|
||||
get addressRaw() {
|
||||
const raw = TYPE_ADDRESS[type](publicKey);
|
||||
return type === 'ethereum'
|
||||
? raw.slice(-20)
|
||||
: raw;
|
||||
},
|
||||
get isLocked() {
|
||||
return isLocked(secretKey);
|
||||
},
|
||||
get meta() {
|
||||
return meta;
|
||||
},
|
||||
get publicKey() {
|
||||
return publicKey;
|
||||
},
|
||||
get type() {
|
||||
return type;
|
||||
},
|
||||
// eslint-disable-next-line sort-keys
|
||||
decodePkcs8,
|
||||
derive: (suri, meta) => {
|
||||
if (type === 'ethereum') {
|
||||
throw new Error('Unable to derive on this keypair');
|
||||
}
|
||||
else if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot derive on a locked keypair');
|
||||
}
|
||||
const { path } = (0, util_crypto_1.keyExtractPath)(suri);
|
||||
const derived = (0, util_crypto_1.keyFromPath)({ publicKey, secretKey }, path, type);
|
||||
return createPair({ toSS58, type }, derived, meta, null);
|
||||
},
|
||||
encodePkcs8: (passphrase) => {
|
||||
return recode(passphrase);
|
||||
},
|
||||
lock: () => {
|
||||
secretKey = new Uint8Array();
|
||||
},
|
||||
setMeta: (additional) => {
|
||||
meta = (0, util_1.objectSpread)({}, meta, additional);
|
||||
},
|
||||
sign: (message, options = {}) => {
|
||||
if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot sign with a locked key pair');
|
||||
}
|
||||
return (0, util_1.u8aConcat)(options.withType
|
||||
? TYPE_PREFIX[type]
|
||||
: SIG_TYPE_NONE, TYPE_SIGNATURE[type]((0, util_1.u8aToU8a)(message), { publicKey, secretKey }));
|
||||
},
|
||||
toJson: (passphrase) => {
|
||||
// NOTE: For ecdsa and ethereum, the publicKey cannot be extracted from the address. For these
|
||||
// pass the hex-encoded publicKey through to the address portion of the JSON (before decoding)
|
||||
// unless the publicKey is already an address
|
||||
const address = ['ecdsa', 'ethereum'].includes(type)
|
||||
? publicKey.length === 20
|
||||
? (0, util_1.u8aToHex)(publicKey)
|
||||
: (0, util_1.u8aToHex)((0, util_crypto_1.secp256k1Compress)(publicKey))
|
||||
: encodeAddress();
|
||||
return (0, toJson_js_1.pairToJson)(type, { address, meta }, recode(passphrase), !!passphrase);
|
||||
},
|
||||
unlock: (passphrase) => {
|
||||
return decodePkcs8(passphrase);
|
||||
},
|
||||
verify: (message, signature, signerPublic) => {
|
||||
return (0, util_crypto_1.signatureVerify)(message, signature, TYPE_ADDRESS[type]((0, util_1.u8aToU8a)(signerPublic))).isValid;
|
||||
},
|
||||
vrfSign: (message, context, extra) => {
|
||||
if (isLocked(secretKey)) {
|
||||
throw new Error('Cannot sign with a locked key pair');
|
||||
}
|
||||
if (type === 'sr25519') {
|
||||
return (0, util_crypto_1.sr25519VrfSign)(message, { secretKey }, context, extra);
|
||||
}
|
||||
const proof = TYPE_SIGNATURE[type]((0, util_1.u8aToU8a)(message), { publicKey, secretKey });
|
||||
return (0, util_1.u8aConcat)(vrfHash(proof, context, extra), proof);
|
||||
},
|
||||
vrfVerify: (message, vrfResult, signerPublic, context, extra) => {
|
||||
if (type === 'sr25519') {
|
||||
return (0, util_crypto_1.sr25519VrfVerify)(message, vrfResult, publicKey, context, extra);
|
||||
}
|
||||
const result = (0, util_crypto_1.signatureVerify)(message, (0, util_1.u8aConcat)(TYPE_PREFIX[type], vrfResult.subarray(32)), TYPE_ADDRESS[type]((0, util_1.u8aToU8a)(signerPublic)));
|
||||
return result.isValid && (0, util_1.u8aEq)(vrfResult.subarray(0, 32), vrfHash(vrfResult.subarray(32), context, extra));
|
||||
}
|
||||
};
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { KeyringPair } from '../types.js';
|
||||
export declare function nobody(): KeyringPair;
|
||||
@@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.nobody = nobody;
|
||||
const publicKey = new Uint8Array(32);
|
||||
const address = '5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM';
|
||||
const meta = {
|
||||
isTesting: true,
|
||||
name: 'nobody'
|
||||
};
|
||||
const json = {
|
||||
address,
|
||||
encoded: '',
|
||||
encoding: {
|
||||
content: ['pkcs8', 'ed25519'],
|
||||
type: 'none',
|
||||
version: '0'
|
||||
},
|
||||
meta
|
||||
};
|
||||
const pair = {
|
||||
address,
|
||||
addressRaw: publicKey,
|
||||
decodePkcs8: (_passphrase, _encoded) => undefined,
|
||||
derive: (_suri, _meta) => pair,
|
||||
encodePkcs8: (_passphrase) => new Uint8Array(0),
|
||||
isLocked: true,
|
||||
lock: () => {
|
||||
// no locking, it is always locked
|
||||
},
|
||||
meta,
|
||||
publicKey,
|
||||
setMeta: (_meta) => undefined,
|
||||
sign: (_message) => new Uint8Array(64),
|
||||
toJson: (_passphrase) => json,
|
||||
type: 'ed25519',
|
||||
unlock: (_passphrase) => undefined,
|
||||
verify: (_message, _signature) => false,
|
||||
vrfSign: (_message, _context, _extra) => new Uint8Array(96),
|
||||
vrfVerify: (_message, _vrfResult, _context, _extra) => false
|
||||
};
|
||||
function nobody() {
|
||||
return pair;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import type { KeypairType } from '@pezkuwi/util-crypto/types';
|
||||
import type { KeyringPair$Json, KeyringPair$Meta } from '../types.js';
|
||||
interface PairStateJson {
|
||||
address: string;
|
||||
meta: KeyringPair$Meta;
|
||||
}
|
||||
export declare function pairToJson(type: KeypairType, { address, meta }: PairStateJson, encoded: Uint8Array, isEncrypted: boolean): KeyringPair$Json;
|
||||
export {};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user