@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.
335 lines (316 loc) • 25.1 kB
JavaScript
// 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
import { sha256 } from "@noble/hashes/sha2.js";
import { randomBytes } from "@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) => 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 (_) {
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
import { str, u32 } from "scale-ts";
var createChainCode = (code) => {
const chainCode = new Uint8Array(32);
chainCode.set(Number.isNaN(+code) ? str.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/utils.ts
import { blake2b } from "@noble/hashes/blake2.js";
import { hexToBytes, isBytes } from "@noble/hashes/utils.js";
import { Bytes, str as str2, Tuple } from "scale-ts";
var blake2b256 = (msg) => blake2b(ensureBytes("msg", msg), { dkLen: 32 });
var blake2b512 = (msg) => 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 = hexToBytes(hex);
} catch (e) {
throw new Error(`${title} must be hex string or Uint8Array, cause: ${e}`);
}
} else if (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__ */ Tuple(str2, 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/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
import { secp256k1 } from "@noble/curves/secp256k1.js";
var ecdsa = {
getPublicKey(privateKey) {
return secp256k1.getPublicKey(ensureBytes("privateKey", privateKey));
},
sign(message, privateKey) {
const recoverableSignature = 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 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
import { ed25519 as ed25519_ } from "@noble/curves/ed25519.js";
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/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
import { getPublicKey, sign, verify } from "@scure/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/sr25519Derive.ts
import { getPublicKey as getPublicKey2, HDKD, secretFromSeed } from "@scure/sr25519";
var sr25519Derive = (seed, curve, derivations) => {
const privateKey = derivations.reduce(
(secretKey, [type, chainCode]) => {
const deriveFn = type === "hard" ? HDKD.secretHard : HDKD.secretSoft;
return deriveFn(secretKey, chainCode);
},
secretFromSeed(seed)
);
const publicKey = getPublicKey2(privateKey);
return {
publicKey,
sign(message) {
return curve.sign(message, privateKey);
}
};
};
// 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/substrateBip39.ts
import { pbkdf2, pbkdf2Async } from "@noble/hashes/pbkdf2.js";
import { sha512 } from "@noble/hashes/sha2.js";
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);
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