@polkadot-labs/hdkd-helpers
Version:
Composable utility functions to generate key pairs for the sr25519, ed25519, and ecdsa cryptographic schemes, along with utilities for hierarchical deterministic (HD) key derivation, tailored for use in the Polkadot and Substrate ecosystems.
389 lines (368 loc) • 27.7 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
BIP39_EN_WORDLIST: () => BIP39_EN_WORDLIST,
DEV_MINI_SECRET: () => DEV_MINI_SECRET,
DEV_PHRASE: () => DEV_PHRASE,
accountId: () => accountId,
blake2b256: () => blake2b256,
blake2b512: () => blake2b512,
createDerive: () => createDerive,
createDeriveKeyPairFn: () => createDeriveKeyPairFn,
ecdsa: () => ecdsa,
ecdsaDerive: () => ecdsaDerive,
ed25519: () => ed25519,
ed25519Derive: () => ed25519Derive,
ensureBytes: () => ensureBytes,
entropyToMiniSecret: () => entropyToMiniSecret,
entropyToMiniSecretAsync: () => entropyToMiniSecretAsync,
entropyToMnemonic: () => entropyToMnemonic,
generateMnemonic: () => generateMnemonic,
mnemonicToEntropy: () => mnemonicToEntropy,
mnemonicToMiniSecret: () => mnemonicToMiniSecret,
mnemonicToMiniSecretAsync: () => mnemonicToMiniSecretAsync,
parseSuri: () => parseSuri,
sr25519: () => sr25519,
sr25519Derive: () => sr25519Derive,
ss58Address: () => ss58Address,
ss58Decode: () => ss58Decode,
ss58Encode: () => ss58Encode,
ss58PublicKey: () => ss58PublicKey,
validateMnemonic: () => validateMnemonic
});
module.exports = __toCommonJS(index_exports);
// src/accountId.ts
var VALID_PUBLICKEY_LENGTHS = [32, 33];
var accountId = (publicKey) => {
publicKey = ensureBytes("publicKey", publicKey);
if (!VALID_PUBLICKEY_LENGTHS.includes(publicKey.length))
throw new Error("Invalid publicKey");
return publicKey.length === 33 ? blake2b256(publicKey) : publicKey;
};
// src/bip39.ts
var import_sha2 = require("@noble/hashes/sha2.js");
var import_utils = require("@noble/hashes/utils.js");
// src/bip39EnWordlist.ts
var BIP39_EN_WORDLIST = "abandon|ability|able|about|above|absent|absorb|abstract|absurd|abuse|access|accident|account|accuse|achieve|acid|acoustic|acquire|across|act|action|actor|actress|actual|adapt|add|addict|address|adjust|admit|adult|advance|advice|aerobic|affair|afford|afraid|again|age|agent|agree|ahead|aim|air|airport|aisle|alarm|album|alcohol|alert|alien|all|alley|allow|almost|alone|alpha|already|also|alter|always|amateur|amazing|among|amount|amused|analyst|anchor|ancient|anger|angle|angry|animal|ankle|announce|annual|another|answer|antenna|antique|anxiety|any|apart|apology|appear|apple|approve|april|arch|arctic|area|arena|argue|arm|armed|armor|army|around|arrange|arrest|arrive|arrow|art|artefact|artist|artwork|ask|aspect|assault|asset|assist|assume|asthma|athlete|atom|attack|attend|attitude|attract|auction|audit|august|aunt|author|auto|autumn|average|avocado|avoid|awake|aware|away|awesome|awful|awkward|axis|baby|bachelor|bacon|badge|bag|balance|balcony|ball|bamboo|banana|banner|bar|barely|bargain|barrel|base|basic|basket|battle|beach|bean|beauty|because|become|beef|before|begin|behave|behind|believe|below|belt|bench|benefit|best|betray|better|between|beyond|bicycle|bid|bike|bind|biology|bird|birth|bitter|black|blade|blame|blanket|blast|bleak|bless|blind|blood|blossom|blouse|blue|blur|blush|board|boat|body|boil|bomb|bone|bonus|book|boost|border|boring|borrow|boss|bottom|bounce|box|boy|bracket|brain|brand|brass|brave|bread|breeze|brick|bridge|brief|bright|bring|brisk|broccoli|broken|bronze|broom|brother|brown|brush|bubble|buddy|budget|buffalo|build|bulb|bulk|bullet|bundle|bunker|burden|burger|burst|bus|business|busy|butter|buyer|buzz|cabbage|cabin|cable|cactus|cage|cake|call|calm|camera|camp|can|canal|cancel|candy|cannon|canoe|canvas|canyon|capable|capital|captain|car|carbon|card|cargo|carpet|carry|cart|case|cash|casino|castle|casual|cat|catalog|catch|category|cattle|caught|cause|caution|cave|ceiling|celery|cement|census|century|cereal|certain|chair|chalk|champion|change|chaos|chapter|charge|chase|chat|cheap|check|cheese|chef|cherry|chest|chicken|chief|child|chimney|choice|choose|chronic|chuckle|chunk|churn|cigar|cinnamon|circle|citizen|city|civil|claim|clap|clarify|claw|clay|clean|clerk|clever|click|client|cliff|climb|clinic|clip|clock|clog|close|cloth|cloud|clown|club|clump|cluster|clutch|coach|coast|coconut|code|coffee|coil|coin|collect|color|column|combine|come|comfort|comic|common|company|concert|conduct|confirm|congress|connect|consider|control|convince|cook|cool|copper|copy|coral|core|corn|correct|cost|cotton|couch|country|couple|course|cousin|cover|coyote|crack|cradle|craft|cram|crane|crash|crater|crawl|crazy|cream|credit|creek|crew|cricket|crime|crisp|critic|crop|cross|crouch|crowd|crucial|cruel|cruise|crumble|crunch|crush|cry|crystal|cube|culture|cup|cupboard|curious|current|curtain|curve|cushion|custom|cute|cycle|dad|damage|damp|dance|danger|daring|dash|daughter|dawn|day|deal|debate|debris|decade|december|decide|decline|decorate|decrease|deer|defense|define|defy|degree|delay|deliver|demand|demise|denial|dentist|deny|depart|depend|deposit|depth|deputy|derive|describe|desert|design|desk|despair|destroy|detail|detect|develop|device|devote|diagram|dial|diamond|diary|dice|diesel|diet|differ|digital|dignity|dilemma|dinner|dinosaur|direct|dirt|disagree|discover|disease|dish|dismiss|disorder|display|distance|divert|divide|divorce|dizzy|doctor|document|dog|doll|dolphin|domain|donate|donkey|donor|door|dose|double|dove|draft|dragon|drama|drastic|draw|dream|dress|drift|drill|drink|drip|drive|drop|drum|dry|duck|dumb|dune|during|dust|dutch|duty|dwarf|dynamic|eager|eagle|early|earn|earth|easily|east|easy|echo|ecology|economy|edge|edit|educate|effort|egg|eight|either|elbow|elder|electric|elegant|element|elephant|elevator|elite|else|embark|embody|embrace|emerge|emotion|employ|empower|empty|enable|enact|end|endless|endorse|enemy|energy|enforce|engage|engine|enhance|enjoy|enlist|enough|enrich|enroll|ensure|enter|entire|entry|envelope|episode|equal|equip|era|erase|erode|erosion|error|erupt|escape|essay|essence|estate|eternal|ethics|evidence|evil|evoke|evolve|exact|example|excess|exchange|excite|exclude|excuse|execute|exercise|exhaust|exhibit|exile|exist|exit|exotic|expand|expect|expire|explain|expose|express|extend|extra|eye|eyebrow|fabric|face|faculty|fade|faint|faith|fall|false|fame|family|famous|fan|fancy|fantasy|farm|fashion|fat|fatal|father|fatigue|fault|favorite|feature|february|federal|fee|feed|feel|female|fence|festival|fetch|fever|few|fiber|fiction|field|figure|file|film|filter|final|find|fine|finger|finish|fire|firm|first|fiscal|fish|fit|fitness|fix|flag|flame|flash|flat|flavor|flee|flight|flip|float|flock|floor|flower|fluid|flush|fly|foam|focus|fog|foil|fold|follow|food|foot|force|forest|forget|fork|fortune|forum|forward|fossil|foster|found|fox|fragile|frame|frequent|fresh|friend|fringe|frog|front|frost|frown|frozen|fruit|fuel|fun|funny|furnace|fury|future|gadget|gain|galaxy|gallery|game|gap|garage|garbage|garden|garlic|garment|gas|gasp|gate|gather|gauge|gaze|general|genius|genre|gentle|genuine|gesture|ghost|giant|gift|giggle|ginger|giraffe|girl|give|glad|glance|glare|glass|glide|glimpse|globe|gloom|glory|glove|glow|glue|goat|goddess|gold|good|goose|gorilla|gospel|gossip|govern|gown|grab|grace|grain|grant|grape|grass|gravity|great|green|grid|grief|grit|grocery|group|grow|grunt|guard|guess|guide|guilt|guitar|gun|gym|habit|hair|half|hammer|hamster|hand|happy|harbor|hard|harsh|harvest|hat|have|hawk|hazard|head|health|heart|heavy|hedgehog|height|hello|helmet|help|hen|hero|hidden|high|hill|hint|hip|hire|history|hobby|hockey|hold|hole|holiday|hollow|home|honey|hood|hope|horn|horror|horse|hospital|host|hotel|hour|hover|hub|huge|human|humble|humor|hundred|hungry|hunt|hurdle|hurry|hurt|husband|hybrid|ice|icon|idea|identify|idle|ignore|ill|illegal|illness|image|imitate|immense|immune|impact|impose|improve|impulse|inch|include|income|increase|index|indicate|indoor|industry|infant|inflict|inform|inhale|inherit|initial|inject|injury|inmate|inner|innocent|input|inquiry|insane|insect|inside|inspire|install|intact|interest|into|invest|invite|involve|iron|island|isolate|issue|item|ivory|jacket|jaguar|jar|jazz|jealous|jeans|jelly|jewel|job|join|joke|journey|joy|judge|juice|jump|jungle|junior|junk|just|kangaroo|keen|keep|ketchup|key|kick|kid|kidney|kind|kingdom|kiss|kit|kitchen|kite|kitten|kiwi|knee|knife|knock|know|lab|label|labor|ladder|lady|lake|lamp|language|laptop|large|later|latin|laugh|laundry|lava|law|lawn|lawsuit|layer|lazy|leader|leaf|learn|leave|lecture|left|leg|legal|legend|leisure|lemon|lend|length|lens|leopard|lesson|letter|level|liar|liberty|library|license|life|lift|light|like|limb|limit|link|lion|liquid|list|little|live|lizard|load|loan|lobster|local|lock|logic|lonely|long|loop|lottery|loud|lounge|love|loyal|lucky|luggage|lumber|lunar|lunch|luxury|lyrics|machine|mad|magic|magnet|maid|mail|main|major|make|mammal|man|manage|mandate|mango|mansion|manual|maple|marble|march|margin|marine|market|marriage|mask|mass|master|match|material|math|matrix|matter|maximum|maze|meadow|mean|measure|meat|mechanic|medal|media|melody|melt|member|memory|mention|menu|mercy|merge|merit|merry|mesh|message|metal|method|middle|midnight|milk|million|mimic|mind|minimum|minor|minute|miracle|mirror|misery|miss|mistake|mix|mixed|mixture|mobile|model|modify|mom|moment|monitor|monkey|monster|month|moon|moral|more|morning|mosquito|mother|motion|motor|mountain|mouse|move|movie|much|muffin|mule|multiply|muscle|museum|mushroom|music|must|mutual|myself|mystery|myth|naive|name|napkin|narrow|nasty|nation|nature|near|neck|need|negative|neglect|neither|nephew|nerve|nest|net|network|neutral|never|news|next|nice|night|noble|noise|nominee|noodle|normal|north|nose|notable|note|nothing|notice|novel|now|nuclear|number|nurse|nut|oak|obey|object|oblige|obscure|observe|obtain|obvious|occur|ocean|october|odor|off|offer|office|often|oil|okay|old|olive|olympic|omit|once|one|onion|online|only|open|opera|opinion|oppose|option|orange|orbit|orchard|order|ordinary|organ|orient|original|orphan|ostrich|other|outdoor|outer|output|outside|oval|oven|over|own|owner|oxygen|oyster|ozone|pact|paddle|page|pair|palace|palm|panda|panel|panic|panther|paper|parade|parent|park|parrot|party|pass|patch|path|patient|patrol|pattern|pause|pave|payment|peace|peanut|pear|peasant|pelican|pen|penalty|pencil|people|pepper|perfect|permit|person|pet|phone|photo|phrase|physical|piano|picnic|picture|piece|pig|pigeon|pill|pilot|pink|pioneer|pipe|pistol|pitch|pizza|place|planet|plastic|plate|play|please|pledge|pluck|plug|plunge|poem|poet|point|polar|pole|police|pond|pony|pool|popular|portion|position|possible|post|potato|pottery|poverty|powder|power|practice|praise|predict|prefer|prepare|present|pretty|prevent|price|pride|primary|print|priority|prison|private|prize|problem|process|produce|profit|program|project|promote|proof|property|prosper|protect|proud|provide|public|pudding|pull|pulp|pulse|pumpkin|punch|pupil|puppy|purchase|purity|purpose|purse|push|put|puzzle|pyramid|quality|quantum|quarter|question|quick|quit|quiz|quote|rabbit|raccoon|race|rack|radar|radio|rail|rain|raise|rally|ramp|ranch|random|range|rapid|rare|rate|rather|raven|raw|razor|ready|real|reason|rebel|rebuild|recall|receive|recipe|record|recycle|reduce|reflect|reform|refuse|region|regret|regular|reject|relax|release|relief|rely|remain|remember|remind|remove|render|renew|rent|reopen|repair|repeat|replace|report|require|rescue|resemble|resist|resource|response|result|retire|retreat|return|reunion|reveal|review|reward|rhythm|rib|ribbon|rice|rich|ride|ridge|rifle|right|rigid|ring|riot|ripple|risk|ritual|rival|river|road|roast|robot|robust|rocket|romance|roof|rookie|room|rose|rotate|rough|round|route|royal|rubber|rude|rug|rule|run|runway|rural|sad|saddle|sadness|safe|sail|salad|salmon|salon|salt|salute|same|sample|sand|satisfy|satoshi|sauce|sausage|save|say|scale|scan|scare|scatter|scene|scheme|school|science|scissors|scorpion|scout|scrap|screen|script|scrub|sea|search|season|seat|second|secret|section|security|seed|seek|segment|select|sell|seminar|senior|sense|sentence|series|service|session|settle|setup|seven|shadow|shaft|shallow|share|shed|shell|sheriff|shield|shift|shine|ship|shiver|shock|shoe|shoot|shop|short|shoulder|shove|shrimp|shrug|shuffle|shy|sibling|sick|side|siege|sight|sign|silent|silk|silly|silver|similar|simple|since|sing|siren|sister|situate|six|size|skate|sketch|ski|skill|skin|skirt|skull|slab|slam|sleep|slender|slice|slide|slight|slim|slogan|slot|slow|slush|small|smart|smile|smoke|smooth|snack|snake|snap|sniff|snow|soap|soccer|social|sock|soda|soft|solar|soldier|solid|solution|solve|someone|song|soon|sorry|sort|soul|sound|soup|source|south|space|spare|spatial|spawn|speak|special|speed|spell|spend|sphere|spice|spider|spike|spin|spirit|split|spoil|sponsor|spoon|sport|spot|spray|spread|spring|spy|square|squeeze|squirrel|stable|stadium|staff|stage|stairs|stamp|stand|start|state|stay|steak|steel|stem|step|stereo|stick|still|sting|stock|stomach|stone|stool|story|stove|strategy|street|strike|strong|struggle|student|stuff|stumble|style|subject|submit|subway|success|such|sudden|suffer|sugar|suggest|suit|summer|sun|sunny|sunset|super|supply|supreme|sure|surface|surge|surprise|surround|survey|suspect|sustain|swallow|swamp|swap|swarm|swear|sweet|swift|swim|swing|switch|sword|symbol|symptom|syrup|system|table|tackle|tag|tail|talent|talk|tank|tape|target|task|taste|tattoo|taxi|teach|team|tell|ten|tenant|tennis|tent|term|test|text|thank|that|theme|then|theory|there|they|thing|this|thought|three|thrive|throw|thumb|thunder|ticket|tide|tiger|tilt|timber|time|tiny|tip|tired|tissue|title|toast|tobacco|today|toddler|toe|together|toilet|token|tomato|tomorrow|tone|tongue|tonight|tool|tooth|top|topic|topple|torch|tornado|tortoise|toss|total|tourist|toward|tower|town|toy|track|trade|traffic|tragic|train|transfer|trap|trash|travel|tray|treat|tree|trend|trial|tribe|trick|trigger|trim|trip|trophy|trouble|truck|true|truly|trumpet|trust|truth|try|tube|tuition|tumble|tuna|tunnel|turkey|turn|turtle|twelve|twenty|twice|twin|twist|two|type|typical|ugly|umbrella|unable|unaware|uncle|uncover|under|undo|unfair|unfold|unhappy|uniform|unique|unit|universe|unknown|unlock|until|unusual|unveil|update|upgrade|uphold|upon|upper|upset|urban|urge|usage|use|used|useful|useless|usual|utility|vacant|vacuum|vague|valid|valley|valve|van|vanish|vapor|various|vast|vault|vehicle|velvet|vendor|venture|venue|verb|verify|version|very|vessel|veteran|viable|vibrant|vicious|victory|video|view|village|vintage|violin|virtual|virus|visa|visit|visual|vital|vivid|vocal|voice|void|volcano|volume|vote|voyage|wage|wagon|wait|walk|wall|walnut|want|warfare|warm|warrior|wash|wasp|waste|water|wave|way|wealth|weapon|wear|weasel|weather|web|wedding|weekend|weird|welcome|west|wet|whale|what|wheat|wheel|when|where|whip|whisper|wide|width|wife|wild|will|win|window|wine|wing|wink|winner|winter|wire|wisdom|wise|wish|witness|wolf|woman|wonder|wood|wool|word|work|world|worry|worth|wrap|wreck|wrestle|wrist|write|wrong|yard|year|yellow|you|young|youth|zebra|zero|zone|zoo";
// src/bip39.ts
var INVALID_MNEMONIC = "Invalid mnemonic";
var INVALID_ENTROPY = "Invalid entropy";
var INVALID_CHECKSUM = "Invalid mnemonic checksum";
var WORDLIST_REQUIRED = "Invalid wordlist";
var parseWordlist = (wordlistStr) => {
const wordlist = wordlistStr.split("|");
if (wordlist.length !== 2048) throw new Error(WORDLIST_REQUIRED);
return wordlist;
};
var deriveChecksumBits = (entropy) => (0, import_sha2.sha256)(entropy)[0].toString(2).padStart(8, "0").slice(0, entropy.length / 4);
var mnemonicToEntropy = (mnemonic, wordlistStr = BIP39_EN_WORDLIST) => {
const words = mnemonic.normalize("NFKD").split(" ");
if (words.length % 3 !== 0 || words.length < 12 || words.length > 24)
throw new Error(INVALID_MNEMONIC);
const wordlist = parseWordlist(wordlistStr);
const bits = words.map((word) => {
const index = wordlist.indexOf(word);
if (index === -1) throw new Error(INVALID_MNEMONIC);
return index.toString(2).padStart(11, "0");
}).join("");
const dividerIndex = bits.length - words.length / 3;
const entropyBytes = bits.slice(0, dividerIndex).match(/(.{1,8})/g)?.map((bin) => Number.parseInt(bin, 2));
if (!entropyBytes || entropyBytes.length < 16 || entropyBytes.length > 32 || entropyBytes.length % 4 !== 0)
throw new Error(INVALID_ENTROPY);
const entropy = Uint8Array.from(entropyBytes);
if (deriveChecksumBits(entropy) !== bits.slice(dividerIndex))
throw new Error(INVALID_CHECKSUM);
return entropy;
};
var entropyToMnemonic = (entropy, wordlistStr = BIP39_EN_WORDLIST) => {
const wordlist = parseWordlist(wordlistStr);
if (!wordlist || wordlist.length !== 2048) throw new Error(WORDLIST_REQUIRED);
if (entropy.length < 16 || entropy.length > 32 || entropy.length % 4 !== 0)
throw new TypeError(INVALID_ENTROPY);
const entropyBits = Array.from(entropy).map((byte) => byte.toString(2).padStart(8, "0")).join("");
return (entropyBits + deriveChecksumBits(entropy)).match(/(.{1,11})/g).map((binary) => wordlist[Number.parseInt(binary, 2)]).join(" ");
};
var generateMnemonic = (strength = 128, wordlist = BIP39_EN_WORDLIST) => entropyToMnemonic((0, import_utils.randomBytes)(strength / 8), wordlist);
var validateMnemonic = (mnemonic, wordlist = BIP39_EN_WORDLIST) => {
try {
mnemonicToEntropy(mnemonic, wordlist);
} catch (_) {
return false;
}
return true;
};
// src/constants.ts
var DEV_PHRASE = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
var DEV_MINI_SECRET = "fac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e";
// src/createChainCode.ts
var import_scale_ts = require("scale-ts");
var createChainCode = (code) => {
const chainCode = new Uint8Array(32);
chainCode.set(Number.isNaN(+code) ? import_scale_ts.str.enc(code) : import_scale_ts.u32.enc(+code));
return chainCode;
};
// src/parseDerivations.ts
var DERIVATION_RE = /(\/{1,2})([^/]+)/g;
var parseDerivations = (derivationsStr) => {
const derivations = [];
for (const [_, type, code] of derivationsStr.matchAll(DERIVATION_RE)) {
derivations.push([type === "//" ? "hard" : "soft", code]);
}
return derivations;
};
// src/utils.ts
var import_blake2 = require("@noble/hashes/blake2.js");
var import_utils2 = require("@noble/hashes/utils.js");
var import_scale_ts2 = require("scale-ts");
var blake2b256 = (msg) => (0, import_blake2.blake2b)(ensureBytes("msg", msg), { dkLen: 32 });
var blake2b512 = (msg) => (0, import_blake2.blake2b)(ensureBytes("msg", msg), { dkLen: 64 });
var ensureBytes = (title, hex, expectedLength) => {
let res;
if (typeof hex === "string") {
try {
if (hex[1] === "x") hex = hex.slice(2);
res = (0, import_utils2.hexToBytes)(hex);
} catch (e) {
throw new Error(`${title} must be hex string or Uint8Array, cause: ${e}`);
}
} else if ((0, import_utils2.isBytes)(hex)) {
res = Uint8Array.from(hex);
} else {
throw new Error(`${title} must be hex string or Uint8Array`);
}
const len = res.length;
if (typeof expectedLength === "number" && len !== expectedLength)
throw new Error(`${title} of length ${expectedLength} expected, got ${len}`);
return res;
};
var derivationCodec = /* @__PURE__ */ (0, import_scale_ts2.Tuple)(import_scale_ts2.str, (0, import_scale_ts2.Bytes)(32), (0, import_scale_ts2.Bytes)(32));
var createDeriveFn = (prefix) => (seed, chainCode) => blake2b256(derivationCodec.enc([prefix, seed, chainCode]));
var createDeriveKeyPairFn = (prefix) => (seed, curve, derivations) => {
const derive = createDeriveFn(prefix);
const privateKey = derivations.reduce((seed2, [type, chainCode]) => {
if (type === "soft") throw new Error("Soft derivations are not supported");
return derive(seed2, chainCode);
}, seed);
return {
publicKey: curve.getPublicKey(privateKey),
sign(message) {
return curve.sign(message, privateKey);
}
};
};
// src/createDerive.ts
var createDerive = ({ seed, curve, derive }) => (path) => derive(
ensureBytes("seed", seed, 32),
{
getPublicKey: (privateKey) => curve.getPublicKey(privateKey),
sign: (message, privateKey) => curve.sign(message, privateKey),
verify: (signature, message, publicKey) => curve.verify(signature, message, publicKey)
},
parseDerivations(path).map(([type, code]) => [
type,
createChainCode(code)
])
);
// src/ecdsa.ts
var import_secp256k1 = require("@noble/curves/secp256k1.js");
var ecdsa = {
getPublicKey(privateKey) {
return import_secp256k1.secp256k1.getPublicKey(ensureBytes("privateKey", privateKey));
},
sign(message, privateKey) {
const recoverableSignature = import_secp256k1.secp256k1.sign(
blake2b256(ensureBytes("message", message)),
ensureBytes("privateKey", privateKey),
{ prehash: false, format: "recovered" }
);
const signature = new Uint8Array(recoverableSignature.length);
signature.set(recoverableSignature.subarray(1, recoverableSignature.length));
signature[recoverableSignature.length] = recoverableSignature[0];
return signature;
},
verify(signature, message, publicKey) {
signature = ensureBytes("signature", signature);
const recoverableSignature = new Uint8Array(signature.length);
recoverableSignature.set(signature.subarray(0, signature.length - 1), 1);
recoverableSignature[0] = signature[recoverableSignature.length];
return import_secp256k1.secp256k1.verify(
recoverableSignature,
blake2b256(ensureBytes("message", message)),
ensureBytes("publicKey", publicKey),
{ prehash: false, format: "recovered" }
);
}
};
// src/ecdsaDerive.ts
var ecdsaDerive = /* @__PURE__ */ createDeriveKeyPairFn("Secp256k1HDKD");
// src/ed25519.ts
var import_ed25519 = require("@noble/curves/ed25519.js");
var ed25519 = {
getPublicKey(privateKey) {
return import_ed25519.ed25519.getPublicKey(ensureBytes("privateKey", privateKey));
},
sign(message, privateKey) {
return import_ed25519.ed25519.sign(
ensureBytes("message", message),
ensureBytes("privateKey", privateKey)
);
},
verify(signature, message, publicKey) {
return import_ed25519.ed25519.verify(
ensureBytes("signature", signature),
ensureBytes("message", message),
ensureBytes("privateKey", publicKey)
);
}
};
// src/ed25519Derive.ts
var ed25519Derive = /* @__PURE__ */ createDeriveKeyPairFn("Ed25519HDKD");
// src/parseSuri.ts
var SURI_RE = /^(\w+(?: \w+)*)((?:\/{1,2}\w+)*)(?:\/{3}(.*))?$/;
var parseSuri = (suri) => {
const [, phrase, paths, password] = SURI_RE.exec(suri) ?? [];
return { phrase, paths, password };
};
// src/sr25519.ts
var import_sr25519 = require("@scure/sr25519");
var sr25519 = {
getPublicKey(privateKey) {
return (0, import_sr25519.getPublicKey)(ensureBytes("privateKey", privateKey, 64));
},
sign(message, privateKey) {
return (0, import_sr25519.sign)(
ensureBytes("privateKey", privateKey, 64),
ensureBytes("message", message)
);
},
verify(signature, message, publicKey) {
return (0, import_sr25519.verify)(
ensureBytes("message", message),
ensureBytes("signature", signature, 64),
ensureBytes("publicKey", publicKey, 32)
);
}
};
// src/sr25519Derive.ts
var import_sr255192 = require("@scure/sr25519");
var sr25519Derive = (seed, curve, derivations) => {
const privateKey = derivations.reduce(
(secretKey, [type, chainCode]) => {
const deriveFn = type === "hard" ? import_sr255192.HDKD.secretHard : import_sr255192.HDKD.secretSoft;
return deriveFn(secretKey, chainCode);
},
(0, import_sr255192.secretFromSeed)(seed)
);
const publicKey = (0, import_sr255192.getPublicKey)(privateKey);
return {
publicKey,
sign(message) {
return curve.sign(message, privateKey);
}
};
};
// src/ss58/ss58.ts
var import_base = require("@scure/base");
var SS58PRE = /* @__PURE__ */ new TextEncoder().encode("SS58PRE");
var CHECKSUM_LENGTH = 2;
var VALID_PAYLOAD_LENGTHS = [32, 33];
var ss58Encode = (payload, prefix = 42) => {
payload = ensureBytes("payload", payload);
if (!VALID_PAYLOAD_LENGTHS.includes(payload.length))
throw new Error("Invalid payload");
const prefixBytes = prefix < 64 ? Uint8Array.of(prefix) : Uint8Array.of(
(prefix & 252) >> 2 | 64,
prefix >> 8 | (prefix & 3) << 6
);
const checksum = blake2b512(
Uint8Array.of(...SS58PRE, ...prefixBytes, ...payload)
).subarray(0, CHECKSUM_LENGTH);
return import_base.base58.encode(Uint8Array.of(...prefixBytes, ...payload, ...checksum));
};
var VALID_ADDRESS_LENGTHS = [35, 36, 37];
var ss58Decode = (addressStr) => {
const address = import_base.base58.decode(addressStr);
if (!VALID_ADDRESS_LENGTHS.includes(address.length))
throw new Error("Invalid address length");
const addressChecksum = address.subarray(address.length - CHECKSUM_LENGTH);
const checksum = blake2b512(
Uint8Array.of(
...SS58PRE,
...address.subarray(0, address.length - CHECKSUM_LENGTH)
)
).subarray(0, CHECKSUM_LENGTH);
if (addressChecksum[0] !== checksum[0] || addressChecksum[1] !== checksum[1])
throw new Error("Invalid checksum");
const prefixLength = address[0] & 64 ? 2 : 1;
const prefix = prefixLength === 1 ? address[0] : (address[0] & 63) << 2 | address[1] >> 6 | (address[1] & 63) << 8;
const payload = address.slice(prefixLength, address.length - CHECKSUM_LENGTH);
return [payload, prefix];
};
// src/ss58/ss58Address.ts
var ss58Address = (publicKey, prefix = 42) => ss58Encode(accountId(publicKey), prefix);
// src/ss58/ss58PublicKey.ts
var ss58PublicKey = ss58Encode;
// src/substrateBip39.ts
var import_pbkdf2 = require("@noble/hashes/pbkdf2.js");
var import_sha22 = require("@noble/hashes/sha2.js");
var salt = (password) => new TextEncoder().encode(`mnemonic${password.normalize("NFKD")}`);
var entropyToMiniSecret = (entropy, password = "") => (0, import_pbkdf2.pbkdf2)(import_sha22.sha512, entropy, salt(password), {
c: 2048,
dkLen: 64
}).slice(0, 32);
var entropyToMiniSecretAsync = async (entropy, password = "") => (await (0, import_pbkdf2.pbkdf2Async)(import_sha22.sha512, entropy, salt(password), {
c: 2048,
dkLen: 64
})).slice(0, 32);
var mnemonicToMiniSecret = (mnemonic, password = "", wordlist = BIP39_EN_WORDLIST) => entropyToMiniSecret(mnemonicToEntropy(mnemonic, wordlist), password);
var mnemonicToMiniSecretAsync = (mnemonic, password = "", wordlist = BIP39_EN_WORDLIST) => entropyToMiniSecretAsync(mnemonicToEntropy(mnemonic, wordlist), password);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BIP39_EN_WORDLIST,
DEV_MINI_SECRET,
DEV_PHRASE,
accountId,
blake2b256,
blake2b512,
createDerive,
createDeriveKeyPairFn,
ecdsa,
ecdsaDerive,
ed25519,
ed25519Derive,
ensureBytes,
entropyToMiniSecret,
entropyToMiniSecretAsync,
entropyToMnemonic,
generateMnemonic,
mnemonicToEntropy,
mnemonicToMiniSecret,
mnemonicToMiniSecretAsync,
parseSuri,
sr25519,
sr25519Derive,
ss58Address,
ss58Decode,
ss58Encode,
ss58PublicKey,
validateMnemonic
});
//# sourceMappingURL=index.cjs.map