@nuwa-ai/identity-kit
Version:
SDK for NIP-1 Agent Single DID Multi-Key Model and NIP-3 CADOP (Custodian-Assisted DID Onboarding Protocol)
1,612 lines (1,587 loc) • 160 kB
JavaScript
#!/usr/bin/env node
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// package.json
var require_package = __commonJS({
"package.json"(exports, module) {
module.exports = {
name: "@nuwa-ai/identity-kit",
version: "0.8.1",
description: "SDK for NIP-1 Agent Single DID Multi-Key Model and NIP-3 CADOP (Custodian-Assisted DID Onboarding Protocol)",
type: "module",
main: "./dist/index.cjs",
module: "./dist/index.js",
types: "./dist/index.d.ts",
bin: {
"nuwa-id": "./dist/cli/index.cjs"
},
exports: {
".": {
types: "./dist/index.d.ts",
import: "./dist/index.js",
require: "./dist/index.cjs"
},
"./web": {
types: "./dist/web/index.d.ts",
import: "./dist/web/index.js",
require: "./dist/web/index.cjs"
},
"./testHelpers": {
types: "./dist/testHelpers/index.d.ts",
import: "./dist/testHelpers/index.js",
require: "./dist/testHelpers/index.cjs"
}
},
scripts: {
dev: "tsup --watch",
build: "tsup && chmod +x dist/cli/index.cjs dist/cli/index.js",
test: "jest --config=jest.config.json",
"test:coverage": "jest --config=jest.config.json --coverage",
"test:watch": "jest --config=jest.config.json --watch",
clean: "rimraf dist",
lint: "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
format: 'prettier --write "src/**/*.ts" "test/**/*.ts"',
"format:check": 'prettier --check "src/**/*.ts" "test/**/*.ts"',
prepublishOnly: "pnpm run clean && pnpm run build"
},
files: [
"dist/**/*"
],
keywords: [
"did",
"identity",
"web3",
"nuwa",
"nip-1",
"nip-3",
"cadop",
"custodian",
"onboarding",
"web",
"browser"
],
peerDependencies: {
react: "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
peerDependenciesMeta: {
react: {
optional: true
}
},
author: "Nuwa Community",
license: "Apache-2.0",
repository: {
type: "git",
url: "git+https://github.com/nuwa-protocol/nuwa.git",
directory: "nuwa-kit/typescript/packages/identity-kit"
},
bugs: {
url: "https://github.com/nuwa-protocol/nuwa/issues"
},
homepage: "https://github.com/nuwa-protocol/nuwa/tree/main/nuwa-kit/typescript/packages/identity-kit#readme",
devDependencies: {
"@jest/globals": "^29.7.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.10.0",
"@types/react": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
eslint: "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
jest: "^29.7.0",
"jest-environment-jsdom": "^30.0.5",
jsdom: "^26.1.0",
prettier: "^3.2.5",
rimraf: "^5.0.5",
"ts-jest": "29.1.1",
tsup: "^8.2.3",
typescript: "^5.3.2"
},
dependencies: {
"@noble/curves": "^1.9.1",
"@noble/hashes": "^1.8.0",
"@roochnetwork/rooch-sdk": "^0.4.0",
multiformats: "^9.9.0"
},
tsup: {
entry: [
"src/index.ts",
"src/web/index.ts",
"src/testHelpers/index.ts",
"src/cli/index.ts"
],
format: [
"esm",
"cjs"
],
dts: true,
splitting: false,
sourcemap: true,
clean: true,
external: [
"react"
]
}
};
}
});
// src/cli/index.ts
import { stat as stat2 } from "fs/promises";
import path2 from "path";
// src/cli/args.ts
function parseArgs(argv) {
if (argv.length === 0) return { options: {} };
const [first, ...tail] = argv;
if (first === "-h" || first === "--help") {
return { command: "help", options: {} };
}
if (first === "-v" || first === "--version") {
return { command: "version", options: {} };
}
if (first.startsWith("-")) {
throw new Error(`Unknown flag: ${first}`);
}
let command = first;
let rest = tail;
if (first === "profile") {
const action = tail[0];
if (!action || action.startsWith("--")) {
throw new Error("profile command requires subcommand: list | use | create");
}
command = `profile:${action}`;
rest = tail.slice(1);
}
const options = {};
for (let i = 0; i < rest.length; i++) {
const token = rest[i];
if (!token.startsWith("-")) continue;
if (token.startsWith("-") && !token.startsWith("--")) {
const flag = token.slice(1);
if (flag === "h") {
addOption(options, "help", true);
continue;
}
if (flag === "v") {
addOption(options, "version", true);
continue;
}
throw new Error(`Unknown flag: -${flag}`);
}
const [rawKey, inlineValue] = token.slice(2).split("=", 2);
if (inlineValue !== void 0) {
addOption(options, rawKey, inlineValue);
continue;
}
const next = rest[i + 1];
if (!next || next.startsWith("--")) {
addOption(options, rawKey, true);
continue;
}
addOption(options, rawKey, next);
i += 1;
}
return { command, options };
}
function addOption(options, key, value) {
const existing = options[key];
if (existing === void 0) {
options[key] = value;
return;
}
if (Array.isArray(existing)) {
existing.push(String(value));
options[key] = existing;
return;
}
options[key] = [String(existing), String(value)];
}
// src/cli-lib/config.ts
import { mkdir, readFile, stat, writeFile } from "fs/promises";
import os from "os";
import path from "path";
// src/cli-lib/types.ts
var DEFAULT_PROFILE_NAME = "default";
function makeDefaultConfig() {
return makeSingleProfileConfig({
name: DEFAULT_PROFILE_NAME,
network: "main",
cadopDomain: "https://id.nuwa.dev",
keyFragment: "agent-auth-1"
});
}
function makeSingleProfileConfig(input) {
return {
version: 2,
activeProfile: input.name,
profiles: {
[input.name]: {
did: input.did,
network: input.network,
roochRpcUrl: input.roochRpcUrl,
cadopDomain: input.cadopDomain,
keyFragment: input.keyFragment,
keyFile: `keys/${input.name}.json`
}
}
};
}
// src/cli-lib/config.ts
function resolveCliDir() {
return path.join(os.homedir(), ".config", "nuwa-did");
}
function getCliPaths() {
const dir = resolveCliDir();
return {
dir,
configFile: path.join(dir, "config.json"),
keysDir: path.join(dir, "keys")
};
}
async function ensureCliDir() {
const paths = getCliPaths();
await mkdir(paths.dir, { recursive: true, mode: 448 });
await mkdir(paths.keysDir, { recursive: true, mode: 448 });
return paths;
}
async function loadConfig() {
const paths = await ensureCliDir();
try {
const raw = await readFile(paths.configFile, "utf8");
try {
return normalizeConfig(JSON.parse(raw));
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(
`invalid nuwa-id config at ${paths.configFile}: ${message}. Delete the file and run \`nuwa-id init\` to recreate it.`
);
}
} catch (error) {
const err = error;
if (!err?.code || err.code !== "ENOENT") {
throw error;
}
return makeDefaultConfig();
}
}
async function saveConfig(config) {
const paths = await ensureCliDir();
await writeFile(paths.configFile, JSON.stringify(config, null, 2), {
encoding: "utf8",
mode: 384
});
}
async function keyExists() {
const config = await loadConfig();
const keyFile = resolveProfileKeyFile(config, config.activeProfile);
try {
await stat(keyFile);
return true;
} catch {
return false;
}
}
async function loadKeyMaterial(profileName) {
const config = await loadConfig();
const keyFile = resolveProfileKeyFile(config, profileName || config.activeProfile);
let raw;
try {
raw = await readFile(keyFile, "utf8");
} catch (error) {
const err = error;
if (err?.code === "ENOENT") {
throw new Error("agent key not initialized; run `nuwa-id init`");
}
throw error;
}
try {
return JSON.parse(raw);
} catch {
throw new Error(`invalid key file at ${keyFile}`);
}
}
async function saveKeyMaterial(key, profileName) {
const config = await loadConfig();
const keyFile = resolveProfileKeyFile(config, profileName || config.activeProfile);
await saveKeyMaterialToPath(key, keyFile);
}
async function saveKeyMaterialWithRelativePath(key, keyFileRelativePath) {
const keyFile = resolveSafeKeyPath(keyFileRelativePath);
await saveKeyMaterialToPath(key, keyFile);
}
async function saveKeyMaterialToPath(key, keyFile) {
const paths = await ensureCliDir();
await mkdir(path.dirname(keyFile), { recursive: true, mode: 448 });
await writeFile(keyFile, JSON.stringify(key, null, 2), {
encoding: "utf8",
mode: 384
});
}
function getActiveProfile(config) {
const profile = config.profiles[config.activeProfile];
if (!profile) {
throw new Error(`active profile not found: ${config.activeProfile}`);
}
return {
name: config.activeProfile,
profile
};
}
function updateActiveProfile(config, updater) {
const active = getActiveProfile(config);
return {
...config,
profiles: {
...config.profiles,
[active.name]: updater(active.profile)
}
};
}
function normalizeConfig(input) {
if (input.version !== 2) {
throw new Error("invalid config version");
}
const activeProfile = input.activeProfile;
if (!activeProfile || typeof activeProfile !== "string") {
throw new Error("invalid config: activeProfile missing");
}
const profiles = input.profiles;
if (!profiles || typeof profiles !== "object") {
throw new Error("invalid config: profiles missing");
}
const active = profiles[activeProfile];
if (!active) {
throw new Error(`invalid config: active profile "${activeProfile}" missing`);
}
return {
version: 2,
activeProfile,
profiles
};
}
function resolveProfileKeyFile(config, profileName) {
const profile = config.profiles[profileName];
if (!profile) {
throw new Error(`profile not found: ${profileName}`);
}
return resolveSafeKeyPath(profile.keyFile, profileName);
}
function resolveSafeKeyPath(keyFile, profileName) {
if (path.isAbsolute(keyFile) || keyFile.includes("..")) {
if (profileName) {
throw new Error(`invalid keyFile in config for profile "${profileName}"`);
}
throw new Error("invalid keyFile path");
}
return path.join(getCliPaths().dir, keyFile);
}
// src/cli-lib/deeplink.ts
import { randomUUID } from "crypto";
// src/multibase/base.ts
import { base58btc } from "multiformats/bases/base58";
import { base64pad, base64, base64url, base64urlpad } from "multiformats/bases/base64";
import { base16 } from "multiformats/bases/base16";
// src/errors/IdentityKitError.ts
var IdentityKitError = class extends Error {
constructor(code, message, options) {
super(message);
this.name = "IdentityKitError";
this.code = code;
this.category = options?.category || this.inferCategory(code);
this.details = options?.details;
this.cause = options?.cause;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
if (options?.cause) {
this.stack = `${this.stack}
Caused by: ${options.cause.stack}`;
}
}
/**
* Infer error category from error code
*/
inferCategory(code) {
if (code.startsWith("AUTH_")) return "authentication";
if (code.startsWith("DID_")) return "did";
if (code.startsWith("VDR_")) return "vdr";
if (code.startsWith("KEY_")) return "key-management";
if (code.startsWith("WEB_")) return "web";
if (code.startsWith("REACT_")) return "react";
if (code.startsWith("CRYPTO_")) return "crypto";
if (code.startsWith("MULTIBASE_")) return "multibase";
if (code.startsWith("SCOPE_") || code.startsWith("VALIDATION_")) return "validation";
if (code.startsWith("DEEPLINK_")) return "deeplink";
if (code.startsWith("STORAGE_")) return "storage";
if (code.startsWith("SIGNER_")) return "signer";
if (code.includes("SIGNING") || code.includes("SIGNATURE")) return "signing";
if (code.includes("NETWORK")) return "network";
if (code.includes("PERMISSION")) return "permission";
return "general";
}
/**
* Convert to a plain object for serialization
*/
toJSON() {
return {
name: this.name,
code: this.code,
category: this.category,
message: this.message,
details: this.details,
stack: this.stack
};
}
/**
* Get a user-friendly error message with suggestions
*/
getUserMessage() {
const suggestions = this.getSuggestions();
let message = this.message;
if (suggestions.length > 0) {
message += "\n\nSuggestions:\n" + suggestions.map((s) => `\u2022 ${s}`).join("\n");
}
return message;
}
/**
* Get contextual suggestions based on error code
*/
getSuggestions() {
switch (this.code) {
case "WEB_BROWSER_NOT_SUPPORTED" /* WEB_BROWSER_NOT_SUPPORTED */:
return [
"Use a modern browser that supports required Web APIs",
"Check if you're running in a browser environment"
];
case "WEB_STORAGE_NOT_AVAILABLE" /* WEB_STORAGE_NOT_AVAILABLE */:
return [
"Enable localStorage or IndexedDB in your browser",
"Check if you're in private/incognito mode",
"Consider using memory storage as fallback"
];
case "DID_METHOD_NOT_SUPPORTED" /* DID_METHOD_NOT_SUPPORTED */:
return [
"Check if the DID method is registered with VDRRegistry",
"Verify the DID format is correct"
];
case "VDR_NETWORK_ERROR" /* VDR_NETWORK_ERROR */:
return [
"Check your network connection",
"Verify the RPC URL is correct and accessible",
"Check if the VDR service is running"
];
case "KEY_STORAGE_ERROR" /* KEY_STORAGE_ERROR */:
return [
"Check browser storage permissions",
"Verify storage quota is not exceeded",
"Try clearing browser storage and retry"
];
case "REACT_NOT_AVAILABLE" /* REACT_NOT_AVAILABLE */:
return [
"Ensure React is properly installed and imported",
"Check if you're using the hook in a React component"
];
case "CRYPTO_PROVIDER_NOT_FOUND" /* CRYPTO_PROVIDER_NOT_FOUND */:
return [
"Check if the key type is supported",
"Verify the crypto provider factory configuration"
];
case "MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */:
return [
"Verify the encoded string format is correct",
"Check if the multibase prefix is valid",
"Ensure the input is not corrupted"
];
case "SCOPE_VALIDATION_FAILED" /* SCOPE_VALIDATION_FAILED */:
return [
"Check the scope format: address::module::function",
"Verify the address format is valid",
"Ensure module and function names are correct"
];
case "DEEPLINK_INVALID_STATE" /* DEEPLINK_INVALID_STATE */:
return [
"Check if the state parameter matches the stored value",
"Verify the callback URL parameters are correct",
"Ensure the session storage is available"
];
case "STORAGE_QUOTA_EXCEEDED" /* STORAGE_QUOTA_EXCEEDED */:
return [
"Clear unused data from browser storage",
"Check available storage quota",
"Consider using a different storage strategy"
];
case "SIGNER_CONVERSION_FAILED" /* SIGNER_CONVERSION_FAILED */:
return [
"Verify the signer implements the required interface",
"Check if the key ID is available in the signer",
"Ensure the DID account signer is properly configured"
];
default:
return [];
}
}
};
function createDIDError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "did",
details,
cause
});
}
function createVDRError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "vdr",
details,
cause
});
}
function createAuthenticationError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "authentication",
details,
cause
});
}
function createCryptoError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "crypto",
details,
cause
});
}
function createMultibaseError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "multibase",
details,
cause
});
}
function createValidationError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "validation",
details,
cause
});
}
function createSignerError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "signer",
details,
cause
});
}
// src/utils/bytes.ts
function stringToBytes(str) {
if (typeof TextEncoder !== "undefined") {
return new TextEncoder().encode(str);
}
if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
return Uint8Array.from(Buffer.from(str, "utf-8"));
}
throw createValidationError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"No TextEncoder or Buffer available in this environment.",
{
environment: typeof globalThis,
textEncoderAvailable: typeof TextEncoder !== "undefined",
bufferAvailable: typeof Buffer !== "undefined"
}
);
}
function bytesToString(bytes) {
if (typeof TextDecoder !== "undefined") {
return new TextDecoder("utf-8").decode(bytes);
}
if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
return Buffer.from(bytes).toString("utf-8");
}
throw createValidationError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"No TextDecoder or Buffer available in this environment.",
{
environment: typeof globalThis,
textDecoderAvailable: typeof TextDecoder !== "undefined",
bufferAvailable: typeof Buffer !== "undefined"
}
);
}
function base64urlToBytes(base64url2) {
const padding = base64url2.length % 4;
const paddedBase64url = base64url2 + "=".repeat(padding === 0 ? 0 : 4 - padding);
const base642 = paddedBase64url.replace(/-/g, "+").replace(/_/g, "/");
const binaryString = atob(base642);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
var Bytes = {
stringToBytes,
bytesToString,
base64urlToBytes
};
// src/multibase/base.ts
var ENCODER_MAP = {
base58btc,
base64pad,
base64,
base64url,
base64urlpad,
base16
};
var MultibaseCodec = class {
/**
* Generic encode
* Example: `MultibaseCodec.encode(bytes, 'base64url')`
*/
static encode(data, base) {
const encoder = ENCODER_MAP[base];
if (!encoder) {
throw createMultibaseError(
"MULTIBASE_ENCODE_FAILED" /* MULTIBASE_ENCODE_FAILED */,
`Unsupported multibase: ${base}`,
{ base, supportedBases: Object.keys(ENCODER_MAP) }
);
}
const bytes = typeof data === "string" ? stringToBytes(data) : data;
return encoder.encode(bytes);
}
/**
* Encode bytes to base58btc format
* @param bytes The bytes to encode
* @returns base58btc encoded string with 'z' prefix
*/
static encodeBase58btc(bytes) {
return this.encode(bytes, "base58btc");
}
/**
* Encode bytes to base64pad format
* @param bytes The bytes to encode
* @returns base64pad encoded string with 'M' prefix
*/
static encodeBase64pad(data) {
return this.encode(data, "base64pad");
}
/**
* Encode bytes to base16 (hex) format
* @param bytes The bytes to encode
* @returns base16 encoded string with 'f' prefix
*/
static encodeBase16(bytes) {
return this.encode(bytes, "base16");
}
/**
* Encode bytes to base64 format
* @param bytes The bytes to encode
* @returns base64 encoded string
*/
static encodeBase64(data) {
return this.encode(data, "base64");
}
/**
* Encode bytes to base64url format (RFC4648 URL-safe, no padding)
* @param bytes The bytes to encode
* @returns base64url encoded string with 'u' prefix
*/
static encodeBase64url(data) {
return this.encode(data, "base64url");
}
/**
* Encode bytes to base64urlpad format (URL-safe with padding)
* @param bytes The bytes to encode
* @returns base64urlpad encoded string with 'U' prefix
*/
static encodeBase64urlpad(data) {
return this.encode(data, "base64urlpad");
}
/**
* Decode base58btc string to bytes
* @param encoded The base58btc encoded string
* @returns decoded bytes
*/
static decodeBase58btc(encoded) {
return base58btc.decode(encoded);
}
/**
* Decode base64pad string to bytes
* @param encoded The base64pad encoded string
* @returns decoded bytes
*/
static decodeBase64pad(encoded) {
return base64pad.decode(encoded);
}
/**
* Decode base16 string to bytes
* @param encoded The base16 encoded string
* @returns decoded bytes
*/
static decodeBase16(encoded) {
return base16.decode(encoded);
}
/**
* Decode base64 string to bytes
* @param encoded The base64 encoded string
* @returns decoded bytes
*/
static decodeBase64(encoded) {
return base64.decode(encoded);
}
/**
* Decode base64url string to bytes
* @param encoded The base64url encoded string
* @returns decoded bytes
*/
static decodeBase64url(encoded) {
return base64url.decode(encoded);
}
/**
* Decode base64url string to string
* @param encoded The base64url encoded string
* @returns decoded string
*/
static decodeBase64urlToString(encoded) {
return bytesToString(this.decodeBase64url(encoded));
}
/**
* Decode base64urlpad string to bytes
* @param encoded The base64urlpad encoded string
* @returns decoded bytes
*/
static decodeBase64urlpad(encoded) {
return base64urlpad.decode(encoded);
}
/**
* Decode base64urlpad string to string
* @param encoded The base64urlpad encoded string
* @returns decoded string
*/
static decodeBase64urlpadToString(encoded) {
return bytesToString(this.decodeBase64urlpad(encoded));
}
/**
* Decode multibase encoded string to bytes
* After multiformats v9, there is no longer a single "universal base" object;
* the official recommendation is to manually dispatch prefixes between the few *.decoder objects you use.
* @param encoded The multibase encoded string
* @returns decoded bytes
*/
static decode(encoded) {
const prefix = encoded[0];
switch (prefix) {
case "z":
return base58btc.decode(encoded);
case "M":
return base64pad.decode(encoded);
case "f":
return base16.decode(encoded);
case "m":
return base64.decode(encoded);
case "u":
return base64url.decode(encoded);
case "U":
return base64urlpad.decode(encoded);
default:
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
`Unsupported multibase prefix: ${prefix}`,
{ prefix, supportedPrefixes: ["z", "M", "m", "u", "U", "f"] }
);
}
}
};
// src/types/crypto.ts
var KeyType = /* @__PURE__ */ ((KeyType7) => {
KeyType7["ED25519"] = "Ed25519VerificationKey2020";
KeyType7["SECP256K1"] = "EcdsaSecp256k1VerificationKey2019";
KeyType7["ECDSAR1"] = "EcdsaSecp256r1VerificationKey2019";
return KeyType7;
})(KeyType || {});
var KEY_TYPE = KeyType;
function isKeyType(value) {
return Object.values(KeyType).includes(value);
}
function toKeyType(value) {
if (isKeyType(value)) {
return value;
}
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Invalid key type: ${value}`,
{ value, supportedTypes: Object.values(KeyType) }
);
}
function keyTypeToRoochSignatureScheme(keyType) {
if (keyType === "EcdsaSecp256k1VerificationKey2019" /* SECP256K1 */) {
return "Secp256k1";
} else if (keyType === "Ed25519VerificationKey2020" /* ED25519 */) {
return "ED25519";
} else if (keyType === "EcdsaSecp256r1VerificationKey2019" /* ECDSAR1 */) {
return "EcdsaR1";
}
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: Object.values(KeyType) }
);
}
// src/multibase/key.ts
var KeyMultibaseCodec = class {
/**
* Encode public key with multicodec prefix
* @param bytes The public key bytes
* @param keyType The key type
* @returns multibase encoded string
*/
static encodeWithType(bytes, keyType) {
const expectedLength = this.getExpectedKeyLength(keyType);
if (bytes.length !== expectedLength) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid key length for ${keyType}. Expected ${expectedLength} bytes, got ${bytes.length}`,
{ keyType, expectedLength, actualLength: bytes.length }
);
}
const prefix = this.getMulticodecPrefix(keyType);
const prefixedKey = this.concatenateBytes(prefix, bytes);
return MultibaseCodec.encodeBase58btc(prefixedKey);
}
/**
* Decode multibase encoded key
* @param encoded The multibase encoded string
* @returns The key type and public key bytes
*/
static decodeWithType(encoded) {
try {
const decoded = MultibaseCodec.decodeBase58btc(encoded);
if (decoded.length < 2) {
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Invalid key format: too short",
{ encoded, minimumLength: 2, actualLength: decoded.length }
);
}
const keyType = this.extractKeyType(decoded);
const bytes = this.extractBytes(decoded);
const expectedLength = this.getExpectedKeyLength(keyType);
if (bytes.length !== expectedLength) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid key length for ${keyType}. Expected ${expectedLength} bytes, got ${bytes.length}`,
{ keyType, expectedLength, actualLength: bytes.length }
);
}
return { keyType, bytes };
} catch (error) {
if (error instanceof Error && error.message === "Non-base58btc character") {
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Invalid multibase format",
{ encoded }
);
}
throw error;
}
}
static getMulticodecPrefix(keyType) {
switch (keyType) {
case KEY_TYPE.ED25519:
return this.ED25519_PREFIX;
case KEY_TYPE.SECP256K1:
return this.SECP256K1_PREFIX;
case KEY_TYPE.ECDSAR1:
return this.ECDSA_R1_PREFIX;
default:
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: [KEY_TYPE.ED25519, KEY_TYPE.SECP256K1, KEY_TYPE.ECDSAR1] }
);
}
}
static concatenateBytes(a, b) {
const result = new Uint8Array(a.length + b.length);
result.set(a);
result.set(b, a.length);
return result;
}
static extractKeyType(prefixedBytes) {
if (prefixedBytes[0] === 237 && prefixedBytes[1] === 1) {
return KEY_TYPE.ED25519;
} else if (prefixedBytes[0] === 231 && prefixedBytes[1] === 1) {
return KEY_TYPE.SECP256K1;
} else if (prefixedBytes[0] === 18 && prefixedBytes[1] === 0) {
return KEY_TYPE.ECDSAR1;
}
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Unknown key type prefix",
{ prefix: Array.from(prefixedBytes.slice(0, 2)) }
);
}
static extractBytes(prefixedBytes) {
return prefixedBytes.slice(2);
}
static getExpectedKeyLength(keyType) {
switch (keyType) {
case KEY_TYPE.ED25519:
return this.ED25519_KEY_LENGTH;
case KEY_TYPE.SECP256K1:
return this.SECP256K1_KEY_LENGTH;
case KEY_TYPE.ECDSAR1:
return this.ECDSA_R1_KEY_LENGTH;
default:
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: [KEY_TYPE.ED25519, KEY_TYPE.SECP256K1, KEY_TYPE.ECDSAR1] }
);
}
}
};
KeyMultibaseCodec.ED25519_PREFIX = new Uint8Array([237, 1]);
KeyMultibaseCodec.SECP256K1_PREFIX = new Uint8Array([231, 1]);
KeyMultibaseCodec.ECDSA_R1_PREFIX = new Uint8Array([18, 0]);
KeyMultibaseCodec.ED25519_KEY_LENGTH = 32;
KeyMultibaseCodec.SECP256K1_KEY_LENGTH = 33;
KeyMultibaseCodec.ECDSA_R1_KEY_LENGTH = 33;
// src/multibase/did.ts
var DidKeyCodec = class {
/**
* Generate did:key from public key
* @param publicKey The public key bytes
* @param keyType The key type
* @returns did:key identifier
*/
static generateDidKey(publicKey, keyType) {
const multibase = KeyMultibaseCodec.encodeWithType(publicKey, keyType);
return `did:key:${multibase}`;
}
/**
* Parse did:key to get key type and public key
* @param didKey The did:key identifier
* @returns The key type and public key bytes
*/
static parseDidKey(didKey) {
if (!didKey.startsWith("did:key:")) {
throw createDIDError("DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */, "Invalid did:key format", {
didKey,
expectedPrefix: "did:key:"
});
}
const multibase = didKey.substring(8);
const { keyType, bytes } = KeyMultibaseCodec.decodeWithType(multibase);
return { keyType, publicKey: bytes };
}
};
// src/deeplink/shared.ts
var LOCALHOST_PATTERN = /^(localhost|\d+\.\d+\.\d+\.\d+)(:\d+)?$/;
function normalizeCadopDomain(cadopDomain) {
const trimmed = cadopDomain.trim().replace(/\/+$/, "");
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
return trimmed;
}
if (LOCALHOST_PATTERN.test(trimmed)) {
return `http://${trimmed}`;
}
return `https://${trimmed}`;
}
function buildAddKeyPayload(input) {
const payload = {
version: 1,
verificationMethod: {
type: input.keyType,
publicKeyMultibase: input.publicKeyMultibase,
idFragment: input.keyFragment
},
verificationRelationships: input.relationships,
redirectUri: input.redirectUri,
state: input.state
};
if (input.agentDid) {
payload.agentDid = input.agentDid;
}
if (input.scopes && input.scopes.length > 0) {
payload.scopes = input.scopes;
}
return payload;
}
function encodeAddKeyPayload(payload) {
return MultibaseCodec.encodeBase64url(JSON.stringify(payload));
}
function buildAddKeyDeepLink(input) {
const domain = normalizeCadopDomain(input.cadopDomain);
const encodedPayload = encodeAddKeyPayload(input.payload);
return `${domain}/add-key?payload=${encodedPayload}`;
}
// src/cli-lib/deeplink.ts
function buildAddKeyDeepLink2(input) {
const domain = normalizeCadopDomain(input.cadopDomain);
const payload = buildAddKeyPayload({
keyType: input.key.keyType,
publicKeyMultibase: input.key.publicKeyMultibase,
keyFragment: input.keyFragment,
relationships: ["authentication"],
redirectUri: input.redirectUri || `${domain}/close`,
state: randomUUID()
});
return {
url: buildAddKeyDeepLink({ cadopDomain: domain, payload }),
payload
};
}
// src/cli-lib/authHeader.ts
import { createHash } from "crypto";
// src/auth/v1/index.ts
var v1_exports = {};
__export(v1_exports, {
AuthErrorCode: () => AuthErrorCode,
createSignature: () => createSignature,
default: () => v1_default,
toAuthorizationHeader: () => toAuthorizationHeader,
verifyAuthHeader: () => verifyAuthHeader,
verifySignature: () => verifySignature
});
// src/auth/v1/utils.ts
function canonicalize(obj) {
const keys = Object.keys(obj).sort();
return JSON.stringify(obj, keys);
}
// src/crypto/providers/ed25519.ts
function getCrypto() {
if (typeof globalThis !== "undefined" && globalThis.crypto) {
return globalThis.crypto;
}
throw createCryptoError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"Web Crypto API is not available in the current runtime",
{ environment: typeof globalThis, cryptoAvailable: false }
);
}
var Ed25519Provider = class {
constructor() {
this.crypto = getCrypto();
}
async generateKeyPair() {
const generated = await this.crypto.subtle.generateKey(
{
name: "Ed25519"
},
true,
["sign", "verify"]
);
if (!("publicKey" in generated)) {
throw createCryptoError(
"CRYPTO_OPERATION_FAILED" /* CRYPTO_OPERATION_FAILED */,
"Ed25519 generateKey did not return a key pair",
{ keyType: "Ed25519", operation: "generateKeyPair" }
);
}
const { publicKey, privateKey } = generated;
const exportedPublic = new Uint8Array(await this.crypto.subtle.exportKey("raw", publicKey));
const exportedPrivate = new Uint8Array(await this.crypto.subtle.exportKey("pkcs8", privateKey));
return {
publicKey: exportedPublic,
privateKey: exportedPrivate
};
}
async sign(data, privateKey) {
let key;
if (privateKey instanceof Uint8Array) {
key = await this.crypto.subtle.importKey(
"pkcs8",
privateKey,
{
name: "Ed25519"
},
false,
["sign"]
);
} else {
key = privateKey;
}
const signature = await this.crypto.subtle.sign("Ed25519", key, data);
return new Uint8Array(signature);
}
async verify(data, signature, publicKey) {
let key;
if (publicKey instanceof Uint8Array) {
key = await this.crypto.subtle.importKey(
"raw",
publicKey,
{
name: "Ed25519"
},
false,
["verify"]
);
} else {
key = await this.crypto.subtle.importKey(
"jwk",
publicKey,
{
name: "Ed25519"
},
false,
["verify"]
);
}
return await this.crypto.subtle.verify("Ed25519", key, signature, data);
}
getKeyType() {
return KEY_TYPE.ED25519;
}
async derivePublicKey(privateKey) {
const cryptoKey = await this.crypto.subtle.importKey(
"pkcs8",
privateKey,
{ name: "Ed25519" },
true,
["sign"]
);
const jwk = await this.crypto.subtle.exportKey("jwk", cryptoKey);
if (!jwk.x) {
throw createCryptoError(
"CRYPTO_KEY_DERIVATION_FAILED" /* CRYPTO_KEY_DERIVATION_FAILED */,
"Failed to derive public key from private key",
{ keyType: "Ed25519", operation: "derivePublicKey" }
);
}
const publicKeyBytes = base64urlToBytes(jwk.x);
return publicKeyBytes;
}
};
// src/crypto/providers/secp256k1.ts
import { secp256k1 } from "@noble/curves/secp256k1";
import { sha256 } from "@noble/hashes/sha256";
var Secp256k1Provider = class {
async generateKeyPair() {
const privateKey = secp256k1.utils.randomPrivateKey();
const publicKey = secp256k1.getPublicKey(privateKey, true);
return {
publicKey,
privateKey
};
}
async sign(data, privateKey) {
if (privateKey instanceof CryptoKey) {
throw createCryptoError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
"CryptoKey is not supported for Secp256k1 signing",
{ keyType: "Secp256k1", operation: "sign", privateKeyType: "CryptoKey" }
);
}
const msgHash = sha256(data);
const signature = secp256k1.sign(msgHash, privateKey);
return signature.toCompactRawBytes();
}
async verify(data, signature, publicKey) {
if (!(publicKey instanceof Uint8Array)) {
throw createCryptoError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
"JsonWebKey is not supported for Secp256k1 verification",
{ keyType: "Secp256k1", operation: "verify", publicKeyType: "JsonWebKey" }
);
}
const msgHash = sha256(data);
return secp256k1.verify(signature, msgHash, publicKey);
}
getKeyType() {
return KEY_TYPE.SECP256K1;
}
async derivePublicKey(privateKey) {
return secp256k1.getPublicKey(privateKey, true);
}
};
// src/crypto/providers/ecdsa_r1.ts
import { p256 } from "@noble/curves/p256";
import { bytesToHex, hexToBytes } from "@noble/curves/abstract/utils";
function getCrypto2() {
if (typeof globalThis !== "undefined" && globalThis.crypto) {
return globalThis.crypto;
}
throw createCryptoError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"Web Crypto API is not available in the current runtime",
{ environment: typeof globalThis, cryptoAvailable: false }
);
}
var EcdsaR1Provider = class {
constructor() {
this.crypto = getCrypto2();
}
async generateKeyPair() {
const generated = await this.crypto.subtle.generateKey(
{
name: "ECDSA",
namedCurve: "P-256"
},
true,
["sign", "verify"]
);
if (!("publicKey" in generated)) {
throw createCryptoError(
"CRYPTO_OPERATION_FAILED" /* CRYPTO_OPERATION_FAILED */,
"ECDSA P-256 generateKey did not return a key pair",
{ keyType: "ECDSA-R1", operation: "generateKeyPair" }
);
}
const { publicKey, privateKey } = generated;
const exportedPublic = new Uint8Array(await this.crypto.subtle.exportKey("raw", publicKey));
const exportedPrivate = new Uint8Array(await this.crypto.subtle.exportKey("pkcs8", privateKey));
const compressedPublicKey = this.compressPublicKey(exportedPublic);
return {
publicKey: compressedPublicKey,
privateKey: exportedPrivate
};
}
compressPublicKey(publicKey) {
if (publicKey.length !== 65) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid public key length. Expected 65 bytes, got ${publicKey.length}`,
{ expectedLength: 65, actualLength: publicKey.length, keyType: "ECDSA-R1" }
);
}
if (publicKey[0] !== 4) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
"Invalid public key format. Expected uncompressed format (0x04)",
{ actualPrefix: publicKey[0], expectedPrefix: 4, keyType: "ECDSA-R1" }
);
}
const x = publicKey.slice(1, 33);
const y = publicKey.slice(33, 65);
const compressedFormat = y[31] % 2 === 0 ? 2 : 3;
const compressed = new Uint8Array(33);
compressed[0] = compressedFormat;
compressed.set(x, 1);
return compressed;
}
decompressPublicKey(compressedKey) {
if (compressedKey.length !== 33) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid compressed public key length. Expected 33 bytes, got ${compressedKey.length}`,
{ expectedLength: 33, actualLength: compressedKey.length, keyType: "ECDSA-R1" }
);
}
const format = compressedKey[0];
if (format !== 2 && format !== 3) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
"Invalid compressed public key format. Expected 0x02 or 0x03",
{ actualPrefix: compressedKey[0], expectedPrefixes: [2, 3], keyType: "ECDSA-R1" }
);
}
try {
const point = p256.ProjectivePoint.fromHex(compressedKey);
const x = point.x;
const y = point.y;
const xBytes = hexToBytes(x.toString(16).padStart(64, "0"));
const yBytes = hexToBytes(y.toString(16).padStart(64, "0"));
const decompressed = new Uint8Array(65);
decompressed[0] = 4;
decompressed.set(xBytes, 1);
decompressed.set(yBytes, 33);
return decompressed;
} catch (err) {
const error = err;
throw createCryptoError(
"CRYPTO_OPERATION_FAILED" /* CRYPTO_OPERATION_FAILED */,
`Failed to decompress public key: ${error.message}`,
{ keyType: "ECDSA-R1", operation: "decompressPublicKey", originalError: error.message }
);
}
}
async sign(data, privateKey) {
let key;
if (privateKey instanceof Uint8Array) {
key = await this.crypto.subtle.importKey(
"pkcs8",
privateKey,
{
name: "ECDSA",
namedCurve: "P-256"
},
false,
["sign"]
);
} else {
key = privateKey;
}
const signature = await this.crypto.subtle.sign(
{
name: "ECDSA",
hash: { name: "SHA-256" }
},
key,
data
);
return new Uint8Array(signature);
}
convertDERSignatureToRaw(derSignature) {
const firstByte = derSignature[0];
if (firstByte === 48) {
try {
const sig = p256.Signature.fromDER(derSignature);
return sig.toCompactRawBytes();
} catch (e) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
"Invalid DER signature",
{ keyType: "ECDSA-R1", operation: "parseDERSignature" }
);
}
}
return derSignature;
}
convertRawToDER(raw) {
if (raw.length !== 64) return raw;
const r = bytesToHex(raw.slice(0, 32));
const s = bytesToHex(raw.slice(32, 64));
const der = p256.Signature.fromCompact(hexToBytes(r + s)).toDERHex();
return hexToBytes(der);
}
async verify(data, signature, publicKey) {
let key;
if (publicKey instanceof Uint8Array) {
const decompressedKey = this.decompressPublicKey(publicKey);
key = await this.crypto.subtle.importKey(
"raw",
decompressedKey,
{
name: "ECDSA",
namedCurve: "P-256"
},
false,
["verify"]
);
} else {
key = await this.crypto.subtle.importKey(
"jwk",
publicKey,
{
name: "ECDSA",
namedCurve: "P-256"
},
false,
["verify"]
);
}
return await this.crypto.subtle.verify(
{
name: "ECDSA",
hash: { name: "SHA-256" }
},
key,
signature,
data
);
}
getKeyType() {
return KEY_TYPE.ECDSAR1;
}
async derivePublicKey(privateKey) {
const cryptoKey = await this.crypto.subtle.importKey(
"pkcs8",
privateKey,
{ name: "ECDSA", namedCurve: "P-256" },
true,
["sign"]
);
const jwk = await this.crypto.subtle.exportKey("jwk", cryptoKey);
if (!jwk.x || !jwk.y) {
throw createCryptoError(
"CRYPTO_KEY_DERIVATION_FAILED" /* CRYPTO_KEY_DERIVATION_FAILED */,
"Failed to derive public key from private key",
{ keyType: "ECDSA-R1", operation: "derivePublicKey" }
);
}
const x = base64urlToBytes(jwk.x);
const y = base64urlToBytes(jwk.y);
const uncompressed = new Uint8Array(65);
uncompressed[0] = 4;
uncompressed.set(x, 1);
uncompressed.set(y, 33);
return this.compressPublicKey(uncompressed);
}
};
// src/crypto/factory.ts
var DefaultCryptoProviderFactory = class {
constructor() {
this.providers = /* @__PURE__ */ new Map();
this.providers.set(KEY_TYPE.ED25519, new Ed25519Provider());
this.providers.set(KEY_TYPE.SECP256K1, new Secp256k1Provider());
this.providers.set(KEY_TYPE.ECDSAR1, new EcdsaR1Provider());
}
createProvider(keyType) {
const provider = this.providers.get(keyType);
if (!provider) {
throw createCryptoError(
"CRYPTO_PROVIDER_NOT_FOUND" /* CRYPTO_PROVIDER_NOT_FOUND */,
`No provider available for key type: ${keyType}`,
{ keyType, availableTypes: Array.from(this.providers.keys()) }
);
}
return provider;
}
supports(keyType) {
return this.providers.has(keyType);
}
};
var defaultCryptoProviderFactory = new DefaultCryptoProviderFactory();
// src/crypto/utils.ts
var CryptoUtils = class {
/**
* Generates a key pair based on the specified curve
* @param type The key type to generate (Ed25519VerificationKey2020 or EcdsaSecp256k1VerificationKey2019 or EcdsaSecp256r1VerificationKey2019)
* @returns A key pair containing public and private keys
*/
static async generateKeyPair(type = "Ed25519VerificationKey2020" /* ED25519 */) {
const keyType = typeof type === "string" ? toKeyType(type) : type;
const provider = defaultCryptoProviderFactory.createProvider(keyType);
return provider.generateKeyPair();
}
/**
* Signs data using the specified private key
* @param data The data to sign
* @param privateKey The private key to use for signing (can be Uint8Array or CryptoKey)
* @param type The key type (Ed25519VerificationKey2020 or EcdsaSecp256k1VerificationKey2019)
* @returns The signature as a Uint8Array
*/
static async sign(data, privateKey, type) {
const keyType = typeof type === "string" ? toKeyType(type) : type;
const provider = defaultCryptoProviderFactory.createProvider(keyType);
return provider.sign(data, privateKey);
}
/**
* Verifies a signature using the specified public key
* @param data The original data
* @param signature The signature to verify
* @param publicKey The public key to use for verification (can be Uint8Array or JsonWebKey)
* @param type The key type (Ed25519VerificationKey2020 or EcdsaSecp256k1VerificationKey2019)
* @returns Whether the signature is valid
*/
static async verify(data, signature, publicKey, type) {
const keyType = typeof type === "string" ? toKeyType(type) : type;
const provider = defaultCryptoProviderFactory.createProvider(keyType);
return provider.verify(data, signature, publicKey);
}
/**
* Derive public key from private key
* @param privateKey The private key bytes
* @param keyType The key type
* @returns The corresponding public key bytes
*/
static async derivePublicKey(privateKey, keyType) {
const type = typeof keyType === "string" ? toKeyType(keyType) : keyType;
const provider = defaultCryptoProviderFactory.createProvider(type);
return provider.derivePublicKey(privateKey);
}
/**
* Validate the consistency between a private key and public key pair
* @param privateKey The private key bytes
* @param publicKey The public key bytes
* @param keyType The key type
* @returns true if the keys are consistent, false otherwise
*/
static async validateKeyPairConsistency(privateKey, publicKey, keyType) {
try {
const derivedPublicKey = await this.derivePublicKey(privateKey, keyType);
return this.areUint8ArraysEqual(derivedPublicKey, publicKey);
} catch (error) {
console.warn("Key pair consistency validation failed:", error);
return false;
}
}
/**
* Compare two Uint8Array for equality
* @param a First array
* @param b Second array
* @returns true if arrays are equal, false otherwise
*/
static areUint8ArraysEqual(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
};
// src/crypto/EcdsaR1PublicKey.ts
import { p256 as p2562 } from "@noble/curves/p256";
import {
RoochAddress,
PublicKey,
SIGNATURE_SCHEME_TO_FLAG,
blake2b,
fromB64
} from "@roochnetwork/rooch-sdk";
var PUBLIC_KEY_SIZE = 33;
var EcdsaR1PublicKey = class extends PublicKey {
/**
* Create a new EcdsaR1PublicKey object
* @param value ECDSA R1 public key as buffer or base-64 encoded string
*/
constructor(value) {
super();
if (typeof value === "string") {
this.data = fromB64(value);
} else if (value instanceof Uint8Array) {
this.data = value;
} else {
this.data = Uint8Array.from(value);
}
if (this.data.length !== PUBLIC_KEY_SIZE) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid public key input. Expected ${PUBLIC_KEY_SIZE} bytes, got ${this.data.length}`,
{ expectedSize: PUBLIC_KEY_SIZE, actualSize: this.data.length, keyType: "ECDSA-R1" }
);
}
}
/**
* Checks if two EcdsaR1 public keys are equal
*/
equals(publicKey) {
return super.equals(publicKey);
}
/**
* Return the byte array representation of the ECDSA R1 public key
*/
toBytes() {
return this.data;
}
/**
* Return the signature scheme flag for ECDSA R1
*/
flag() {
return SIGNATURE_SCHEME_TO_FLAG.EcdsaR1;
}
/**
* Verifies that the signature is valid for the provided message
*/
async verify(message, signature) {
try {
return p2562.verify(signature, message, this.toBytes());
} catch (error) {
return false;
}
}
/**
* Return the Rooch address associated with this ECDSA R1 public key
*/
toAddress() {
const tmp = new Uint8Array(PUBLIC_KEY_SIZE + 1);
tmp.set([SIGNATURE_SCHEME_TO_FLAG.EcdsaR1]);
tmp.set(this.toBytes(), 1);
const ROOCH_ADDRESS_L