@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.
315 lines (296 loc) • 24.4 kB
JavaScript
// src/constants.ts
var DEV_PHRASE = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
var DEV_MINI_SECRET = "fac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e";
// src/utils.ts
import { ensureBytes as ensureBytes_ } from "@noble/curves/abstract/utils";
import { blake2b } from "@noble/hashes/blake2b";
import { Bytes, Tuple, str } from "scale-ts";
var blake2b256 = (msg) => blake2b(msg, { dkLen: 32 });
var blake2b512 = (msg) => blake2b(msg, { dkLen: 64 });
var ensureBytes = (title, hex, expectedLength) => {
if (typeof hex === "string" && hex[1] === "x") hex = hex.slice(2);
return ensureBytes_(title, hex, expectedLength);
};
var derivationCodec = /* @__PURE__ */ Tuple(str, Bytes(32), 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/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/ss58/ss58.ts
import { base58 } from "@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 base58.encode(Uint8Array.of(...prefixBytes, ...payload, ...checksum));
};
var VALID_ADDRESS_LENGTHS = [35, 36, 37];
var ss58Decode = (addressStr) => {
const address = 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/bip39.ts
import { sha256 } from "@noble/hashes/sha256";
import { randomBytes } from "@noble/hashes/utils";
// 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) => 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(randomBytes(strength / 8), wordlist);
var validateMnemonic = (mnemonic, wordlist = BIP39_EN_WORDLIST) => {
try {
mnemonicToEntropy(mnemonic, wordlist);
} catch (e) {
return false;
}
return true;
};
// src/substrateBip39.ts
import { pbkdf2, pbkdf2Async } from "@noble/hashes/pbkdf2";
import { sha512 } from "@noble/hashes/sha512";
var salt = (password) => new TextEncoder().encode(`mnemonic${password.normalize("NFKD")}`);
var entropyToMiniSecret = (entropy, password = "") => pbkdf2(sha512, entropy, salt(password), {
c: 2048,
dkLen: 64
}).slice(0, 32);
var entropyToMiniSecretAsync = async (entropy, password = "") => (await pbkdf2Async(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);
// 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/ecdsa.ts
import { secp256k1 } from "@noble/curves/secp256k1";
var ecdsa = {
getPublicKey(privateKey) {
return secp256k1.getPublicKey(ensureBytes("privateKey", privateKey));
},
sign(message, privateKey) {
const signature = secp256k1.sign(
blake2b256(ensureBytes("message", message)),
ensureBytes("privateKey", privateKey)
);
const signedBytes = signature.toCompactRawBytes();
const out = new Uint8Array(signedBytes.length + 1);
out.set(signedBytes);
out[signedBytes.length] = signature.recovery;
return out;
},
verify(signature, message, publicKey) {
return secp256k1.verify(
secp256k1.Signature.fromCompact(
ensureBytes("signature", signature).slice(0, 64)
),
blake2b256(ensureBytes("message", message)),
ensureBytes("publicKey", publicKey)
);
}
};
// src/ed25519.ts
import { ed25519 as ed25519_ } from "@noble/curves/ed25519";
var ed25519 = {
getPublicKey(privateKey) {
return ed25519_.getPublicKey(ensureBytes("privateKey", privateKey));
},
sign(message, privateKey) {
return ed25519_.sign(
ensureBytes("message", message),
ensureBytes("privateKey", privateKey)
);
},
verify(signature, message, publicKey) {
return ed25519_.verify(
ensureBytes("signature", signature),
ensureBytes("message", message),
ensureBytes("privateKey", publicKey)
);
}
};
// src/sr25519.ts
import { getPublicKey, sign, verify } from "micro-sr25519";
var sr25519 = {
getPublicKey(privateKey) {
return getPublicKey(ensureBytes("privateKey", privateKey, 64));
},
sign(message, privateKey) {
return sign(
ensureBytes("privateKey", privateKey, 64),
ensureBytes("message", message)
);
},
verify(signature, message, publicKey) {
return verify(
ensureBytes("message", message),
ensureBytes("signature", signature, 64),
ensureBytes("publicKey", publicKey, 32)
);
}
};
// src/ecdsaDerive.ts
var ecdsaDerive = /* @__PURE__ */ createDeriveKeyPairFn("Secp256k1HDKD");
// src/ed25519Derive.ts
var ed25519Derive = /* @__PURE__ */ createDeriveKeyPairFn("Ed25519HDKD");
// src/sr25519Derive.ts
import { randomBytes as randomBytes2 } from "@noble/hashes/utils";
import { HDKD, getPublicKey as getPublicKey2, secretFromSeed } from "micro-sr25519";
var sr25519Derive = (seed, curve, derivations) => {
const privateKey = derivations.reduce(
(secretKey, [type, chainCode]) => type === "hard" ? HDKD.secretHard(secretKey, chainCode) : HDKD.secretSoft(secretKey, chainCode, randomBytes2),
secretFromSeed(seed)
);
const publicKey = getPublicKey2(privateKey);
return {
publicKey,
sign(message) {
return curve.sign(message, privateKey);
}
};
};
// src/createChainCode.ts
import { str as str2, u32 } from "scale-ts";
var createChainCode = (code) => {
const chainCode = new Uint8Array(32);
chainCode.set(Number.isNaN(+code) ? str2.enc(code) : 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/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)
])
);
export {
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.js.map