From 915485d032d7ef36adda3f6311aaaeaf5abee7ad Mon Sep 17 00:00:00 2001 From: xt0x Date: Sun, 29 Mar 2026 06:39:40 +0900 Subject: [PATCH 1/3] chore(.gitignore): remove references directory from ignore list --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index f31cb8f..1bb15bc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,6 @@ # AGENTS.md file /AGENTS.md -# References directory -/references - # assets/fonts is ignored by default. assets/fonts/**/* assets/fonts/**/* From bba1328f68077bff771bd7787b6320885a251d9e Mon Sep 17 00:00:00 2001 From: xt0x Date: Sun, 29 Mar 2026 06:45:58 +0900 Subject: [PATCH 2/3] feat(mnemonic): add fake wordlist assets and svg render scripts --- assets/mnemonic/fake-wordlist.json | 2050 +++++++++++++++++++ package.json | 4 +- pnpm-lock.yaml | 19 + scripts/generate-fake-mnemonic-wordlist.mjs | 55 + scripts/render-svg-fake-mnemonic.mjs | 120 ++ 5 files changed, 2247 insertions(+), 1 deletion(-) create mode 100644 assets/mnemonic/fake-wordlist.json create mode 100644 scripts/generate-fake-mnemonic-wordlist.mjs create mode 100644 scripts/render-svg-fake-mnemonic.mjs diff --git a/assets/mnemonic/fake-wordlist.json b/assets/mnemonic/fake-wordlist.json new file mode 100644 index 0000000..3c3b7b1 --- /dev/null +++ b/assets/mnemonic/fake-wordlist.json @@ -0,0 +1,2050 @@ +[ + "overhent", + "oilway", + "refence", + "span", + "honeying", + "diarized", + "hippos", + "porges", + "cierge", + "chaperon", + "disced", + "newcomer", + "midweek", + "mudhooks", + "stemed", + "cist", + "retroact", + "sunbeams", + "ungazing", + "capons", + "helicon", + "reglow", + "lithify", + "redtop", + "tortuous", + "care", + "bebungs", + "disks", + "coherers", + "tooter", + "ashiver", + "glume", + "chow", + "manred", + "tabards", + "zastruga", + "quackles", + "latices", + "spoke", + "quota", + "bruit", + "munited", + "smolder", + "titans", + "danelagh", + "unhatted", + "costed", + "rogue", + "maxi", + "recuse", + "buy", + "furies", + "doody", + "schisma", + "doggy", + "limner", + "savorous", + "nomadic", + "munis", + "decrowns", + "repaves", + "dimplier", + "vista", + "adjurers", + "pretest", + "rotundas", + "culty", + "magician", + "detainer", + "forcats", + "facedown", + "flunked", + "airflows", + "dewools", + "gainer", + "vicinity", + "arbour", + "guans", + "haqueton", + "cebids", + "lakebed", + "turbot", + "femality", + "gagging", + "lofts", + "wuzzling", + "glugging", + "crenelle", + "stime", + "witless", + "fatten", + "haplite", + "embarked", + "dauby", + "refutals", + "doomiest", + "pewterer", + "conquest", + "ringmen", + "kokas", + "recoal", + "kabbalah", + "creatrix", + "appals", + "diamante", + "tenotomy", + "pome", + "whiptail", + "suckens", + "umpies", + "raptured", + "cark", + "chancier", + "ornithic", + "latish", + "ripe", + "tupping", + "ants", + "sore", + "humider", + "curating", + "ogee", + "kurveys", + "noria", + "beeps", + "zzzs", + "fishlike", + "foragers", + "gurges", + "mar", + "magazine", + "awl", + "toucanet", + "troubles", + "oribis", + "laipses", + "tappings", + "clubby", + "manreds", + "prelives", + "outbribe", + "nitro", + "tessera", + "pommels", + "nostril", + "digraph", + "quinoid", + "stipule", + "pether", + "deployer", + "draying", + "stinker", + "akirahos", + "depone", + "enzymes", + "punning", + "lustful", + "filibegs", + "rashes", + "aliyah", + "jollity", + "capi", + "lohan", + "brasils", + "craters", + "ales", + "dasheen", + "gees", + "nodi", + "seedmen", + "toluates", + "ropiest", + "deleting", + "mpret", + "hoot", + "asterid", + "cassene", + "nobelium", + "farding", + "begrime", + "gumdrops", + "elutors", + "skoaling", + "togated", + "chefed", + "maul", + "gombro", + "yellers", + "flashily", + "bicycles", + "holdalls", + "sixmos", + "deprive", + "recoding", + "unwilful", + "granted", + "geoidal", + "speakers", + "phalloid", + "roundle", + "eluviums", + "rewaxes", + "fourthly", + "narwhale", + "farinhas", + "caudles", + "sangers", + "springle", + "gamboes", + "fudge", + "gabblers", + "agutis", + "recasts", + "catatony", + "botonnee", + "samadhis", + "freedom", + "yew", + "nummular", + "monotype", + "ataraxy", + "poring", + "finnesko", + "sickbed", + "dough", + "gedacts", + "accidie", + "unwitty", + "stonings", + "karst", + "torics", + "steer", + "missent", + "helios", + "floshes", + "saxicole", + "pterin", + "drongos", + "woops", + "bodach", + "choruses", + "mooloos", + "akenial", + "splodged", + "urd", + "outjest", + "latterly", + "accrued", + "filthier", + "vilde", + "epiblast", + "scutum", + "diarchic", + "mislike", + "skywrote", + "scarfs", + "tacnodes", + "bey", + "eeven", + "feria", + "savable", + "hammocks", + "pedler", + "cedillas", + "sorehon", + "untame", + "belayed", + "phi", + "glottis", + "fem", + "snoozer", + "filmable", + "whilk", + "daedal", + "chucker", + "alaska", + "apso", + "thrip", + "liefs", + "flanerie", + "pashim", + "staretz", + "chisel", + "escapist", + "quints", + "unsexual", + "rheumed", + "toadflax", + "expired", + "yojana", + "overflow", + "spadger", + "nappes", + "busywork", + "stirres", + "knawe", + "hounders", + "canticle", + "degust", + "annattos", + "rooted", + "dows", + "alec", + "clusias", + "undress", + "meneer", + "fetiches", + "glancer", + "tupiks", + "radded", + "flanch", + "gisarme", + "tums", + "kuia", + "flanger", + "sensate", + "behoove", + "jimmy", + "idling", + "qualia", + "corrade", + "coverlid", + "cusp", + "trevises", + "sucuruju", + "boneset", + "kebele", + "outsworn", + "gave", + "curacaos", + "slovenly", + "delo", + "cricoids", + "testable", + "fanion", + "lampoons", + "eildings", + "uncoils", + "quay", + "tort", + "kalpis", + "leavy", + "berimed", + "magisms", + "pappies", + "fireman", + "kababbed", + "smirring", + "schlep", + "unfeared", + "outacts", + "bothies", + "veil", + "hissiest", + "resident", + "satara", + "unclamp", + "being", + "vowesses", + "slag", + "snabbles", + "maleate", + "disponee", + "boxboard", + "preelect", + "sauna", + "unsinew", + "domes", + "skudlers", + "fluellin", + "fisheyes", + "dumpster", + "tramples", + "denotes", + "nerds", + "fluorine", + "renagued", + "reliques", + "vaporize", + "oestriol", + "meshugah", + "tubulure", + "spotlit", + "reactive", + "avanti", + "pushing", + "plies", + "fivefold", + "ergotism", + "seconded", + "natiform", + "labdas", + "gingkos", + "tilapias", + "arsheens", + "domic", + "braless", + "egressed", + "stramony", + "defat", + "usure", + "bedhead", + "avyzed", + "mashes", + "claques", + "vivace", + "sereins", + "brantail", + "oleander", + "ramparts", + "bigot", + "phonate", + "jazzes", + "golds", + "fanglike", + "resound", + "slain", + "waxcloth", + "toponymy", + "thinly", + "visive", + "snowshed", + "tore", + "frory", + "visibly", + "isodoma", + "labours", + "picoline", + "pretyped", + "apehood", + "prawn", + "metazoon", + "baptize", + "platanna", + "ruefully", + "ellwand", + "bries", + "brangles", + "politick", + "scrorp", + "correas", + "neckweed", + "propped", + "pedocal", + "trusty", + "kins", + "avengers", + "enwound", + "repolled", + "dimer", + "gazebo", + "thowels", + "damozels", + "unnest", + "rowt", + "neosouls", + "stonks", + "bylane", + "cotyles", + "birkiest", + "jailed", + "soldiery", + "griff", + "summa", + "grouter", + "mirths", + "prance", + "jasy", + "grizzles", + "zaires", + "rakish", + "creepier", + "dogsbody", + "glycyls", + "lullers", + "buglets", + "fivepins", + "hilly", + "gonidium", + "trawlers", + "saris", + "skurried", + "scrine", + "briquet", + "scissil", + "croons", + "swealed", + "jabirus", + "jetes", + "unbones", + "zeps", + "elastics", + "yashmaks", + "ferer", + "quops", + "consters", + "geyer", + "jouking", + "primatal", + "euphonia", + "most", + "troll", + "cardecus", + "forging", + "aculeate", + "turgent", + "stylops", + "lode", + "stiffing", + "stood", + "lairage", + "yokozuna", + "dragees", + "malmy", + "carpals", + "harmonic", + "kolkozy", + "gauging", + "debacle", + "elmen", + "dankness", + "merles", + "mugwort", + "droughts", + "farcing", + "rerises", + "decks", + "tough", + "rinkhals", + "pettings", + "pultures", + "noyes", + "gazettes", + "gerned", + "hurlings", + "tolans", + "troupers", + "molimen", + "letup", + "grotto", + "siss", + "raciest", + "scalled", + "rushed", + "datacard", + "kora", + "weewee", + "hemiolia", + "envelops", + "clubfoot", + "griseous", + "entitle", + "squads", + "dyingly", + "dinted", + "groughs", + "prefires", + "chagans", + "vroomed", + "prosects", + "sieths", + "redds", + "canner", + "unrights", + "bandster", + "hexaplar", + "actinal", + "leister", + "rightly", + "farness", + "zonae", + "naughty", + "ringwise", + "sage", + "apolog", + "ancillae", + "trudge", + "rankles", + "exomises", + "bendayed", + "steeld", + "daiquiri", + "oxalates", + "ignatia", + "ammonoid", + "boying", + "weized", + "pumicing", + "hyssops", + "wived", + "oflags", + "varsal", + "alkine", + "himation", + "mullah", + "futural", + "ions", + "chametz", + "louing", + "naumachy", + "touches", + "kirri", + "somewhen", + "maudlin", + "vouge", + "sukkahs", + "galyak", + "teentsy", + "impels", + "clipt", + "cymene", + "corder", + "sylvines", + "bittacle", + "queriers", + "domines", + "sloom", + "tenders", + "wastfull", + "septal", + "cakings", + "cruzies", + "spongers", + "ansae", + "blueys", + "meneers", + "octanes", + "izzats", + "reincite", + "surfboat", + "khotbehs", + "malt", + "bumper", + "gurgling", + "goutte", + "reenacts", + "hydriae", + "pretape", + "helpmeet", + "poets", + "pends", + "thoriums", + "woodiest", + "myoma", + "hups", + "keelhale", + "teazels", + "ameiosis", + "baloneys", + "simmered", + "mayan", + "yexing", + "lopsided", + "cocomat", + "provand", + "saggar", + "hackled", + "thiram", + "schoolie", + "variolar", + "marranos", + "payload", + "sakkoses", + "bidi", + "northing", + "glitchy", + "nandine", + "beryline", + "shikaris", + "alifs", + "burdener", + "piglings", + "executer", + "urp", + "ergos", + "notching", + "lockful", + "healees", + "twocker", + "toluide", + "panmixia", + "benaming", + "anelace", + "loved", + "brussels", + "adhibits", + "piler", + "runlet", + "balletic", + "woolman", + "skulls", + "assemble", + "amberoid", + "resins", + "tuilzied", + "amputate", + "acidiest", + "rimples", + "imparter", + "kicked", + "agee", + "atone", + "byplays", + "fulvous", + "enlight", + "syrinxes", + "slurban", + "agile", + "zingy", + "groned", + "cablings", + "scrimper", + "sphairee", + "lorises", + "gorms", + "madzoon", + "reprice", + "furors", + "accused", + "warmer", + "snuck", + "metage", + "saurels", + "pecke", + "aspidia", + "condom", + "uredia", + "paspalum", + "scrying", + "pryses", + "centum", + "sadhanas", + "anergies", + "spored", + "scraped", + "diffuser", + "unclipt", + "junkers", + "clomped", + "shoppe", + "prologue", + "aucepses", + "asway", + "pedagog", + "basidium", + "stonied", + "confuse", + "misyoke", + "hormic", + "ironless", + "tumbling", + "misplace", + "maltoses", + "cams", + "botchily", + "chimbs", + "inhuman", + "ridgetop", + "cautel", + "fur", + "sended", + "cruzado", + "debyes", + "vervets", + "woodbine", + "nadir", + "rems", + "odd", + "opcodes", + "matrons", + "bedash", + "glaziest", + "ganging", + "slates", + "jaseys", + "nonagon", + "romcoms", + "mangels", + "unnails", + "mistype", + "stiffie", + "avosets", + "oaf", + "onefold", + "pulkha", + "arroyo", + "kanehs", + "contra", + "dorring", + "biphenyl", + "menshen", + "shottles", + "fastly", + "renminbi", + "cohoe", + "worrels", + "grimmest", + "classes", + "linked", + "cranes", + "daynt", + "peltless", + "haylofts", + "suffari", + "shootout", + "defrocks", + "goldfish", + "cobia", + "shariah", + "dortier", + "squished", + "popped", + "pawky", + "penlight", + "rodded", + "styring", + "bludge", + "nudniks", + "curbs", + "gesse", + "anxious", + "bubbly", + "pelorias", + "audial", + "chekists", + "undrew", + "gripsack", + "optant", + "programs", + "bags", + "allaying", + "rounders", + "piths", + "chlorous", + "cimex", + "shiniest", + "lefts", + "cinched", + "kaneh", + "waxable", + "bibb", + "telamon", + "oaty", + "eyas", + "cheapy", + "preforms", + "dummier", + "fitter", + "lits", + "mixdown", + "atalaya", + "rebounds", + "coupee", + "cucumber", + "emits", + "retiree", + "flagless", + "yon", + "webisode", + "sizel", + "declared", + "cunettes", + "colleen", + "cupped", + "rubels", + "sherris", + "goolies", + "sodium", + "subtheme", + "fatback", + "blinking", + "peachier", + "kindle", + "gimmes", + "raincoat", + "jilgies", + "harmala", + "degassed", + "lootings", + "earthset", + "eyra", + "toasts", + "cyprids", + "traveled", + "haftara", + "hiders", + "sabhas", + "peyotl", + "laevulin", + "compeers", + "dumbshit", + "bauchled", + "factful", + "bunchy", + "obols", + "tartufo", + "fluorids", + "kainga", + "testatum", + "roadsman", + "sodomist", + "stotters", + "fidged", + "presides", + "sourdine", + "recombs", + "treviss", + "embayed", + "holloos", + "bikkies", + "asswages", + "pates", + "doy", + "elaters", + "shnapps", + "cackier", + "mundic", + "mouflon", + "gutless", + "rewords", + "tensive", + "folded", + "twinning", + "nonnasal", + "zootypic", + "crazies", + "hawse", + "carousel", + "costards", + "wattless", + "overlend", + "soutar", + "quadding", + "compeer", + "zeniths", + "slinging", + "capacity", + "scarves", + "pedaling", + "loosener", + "redons", + "podcast", + "bumbazes", + "nagors", + "apraxic", + "pies", + "dumpcart", + "marri", + "haggish", + "sunbeamy", + "romaika", + "veins", + "renests", + "hoaxes", + "blazars", + "reerects", + "snelling", + "aromatic", + "are", + "rits", + "pickmaw", + "ptisans", + "resewn", + "hexapody", + "motific", + "moline", + "egoist", + "upclosed", + "brocard", + "jeeps", + "magg", + "scrawmed", + "dubbos", + "canape", + "trouse", + "backload", + "eucyclic", + "bathed", + "purpures", + "snelled", + "pittered", + "vawting", + "temple", + "junked", + "epizoism", + "cough", + "gladder", + "leaflet", + "deixises", + "corbeaus", + "bladder", + "portance", + "fifer", + "feoffer", + "maladies", + "deticks", + "woggle", + "saying", + "fondant", + "debur", + "metump", + "rainfall", + "overswim", + "holsters", + "nonnaval", + "hydyne", + "unbosoms", + "napoleon", + "stadda", + "rugae", + "whizzers", + "rurus", + "enframe", + "devoted", + "aerobot", + "apanaged", + "chariest", + "whitlow", + "extruded", + "guidable", + "kation", + "impresa", + "lingerie", + "kab", + "banalise", + "puggy", + "atebrins", + "moblogs", + "cockbird", + "scrike", + "trimixes", + "yobbos", + "trigging", + "unwive", + "mapless", + "splicers", + "atoke", + "incisor", + "emparing", + "caped", + "deploy", + "ludships", + "inactive", + "podlike", + "beamy", + "inchases", + "chapels", + "raphias", + "pitiably", + "darzis", + "settlers", + "burnt", + "yerding", + "adequacy", + "michts", + "mor", + "tempos", + "foibles", + "dungaree", + "offeree", + "pooja", + "idealogy", + "tetrapod", + "monofil", + "bespate", + "warden", + "mommet", + "dowery", + "loudlier", + "mercers", + "oolitic", + "doveish", + "limbier", + "goldtone", + "swinish", + "sfumato", + "tribrach", + "felid", + "prees", + "purl", + "hilloes", + "honoring", + "imagists", + "has", + "whipray", + "dormancy", + "chode", + "thraldom", + "lizards", + "poneys", + "shelling", + "livened", + "matronal", + "marled", + "crankly", + "untailed", + "thofts", + "canikins", + "soukous", + "bleepers", + "noilier", + "smarming", + "reviles", + "reraised", + "peccant", + "biers", + "tetrodes", + "bigwig", + "opossum", + "dislikes", + "econuts", + "mammet", + "upheaved", + "dipt", + "aviate", + "protocol", + "drawlier", + "dights", + "upmakers", + "exogen", + "carney", + "glunched", + "nova", + "pennyfee", + "aristo", + "dogmata", + "mysosts", + "odored", + "menomini", + "woofer", + "turquois", + "coccos", + "rescuing", + "anestra", + "mill", + "garials", + "puggled", + "sprit", + "acarbose", + "dejeune", + "heniquen", + "sonorant", + "hulkiest", + "qibla", + "stypsis", + "evolver", + "boxroom", + "foxings", + "markhoor", + "kappa", + "furrs", + "quelea", + "faithers", + "buyout", + "theocrat", + "atomisms", + "spilths", + "plex", + "cursory", + "pooting", + "jolts", + "butanone", + "foams", + "awed", + "palmtops", + "cepheids", + "preeved", + "afforest", + "krytron", + "sukuks", + "chokra", + "shiatsu", + "glurge", + "ichs", + "toustier", + "rattens", + "mockups", + "yeading", + "gennaker", + "deboners", + "cubicle", + "weete", + "unborn", + "rave", + "eddish", + "filthy", + "coolies", + "unipods", + "topsider", + "hippuric", + "budgerow", + "redacts", + "ledgered", + "chunkier", + "belah", + "spender", + "suiters", + "overword", + "sternums", + "yecchs", + "soyle", + "keirin", + "resits", + "scugged", + "sheesh", + "babkas", + "culming", + "tofutti", + "celiacs", + "resawing", + "modiolus", + "alencons", + "misbuild", + "coupers", + "bien", + "tar", + "regroom", + "moilers", + "opercula", + "fas", + "scienced", + "chufa", + "shirred", + "eyer", + "conation", + "bhels", + "amabile", + "duvetyns", + "cresol", + "yachts", + "rehinge", + "sybow", + "shingles", + "dadahs", + "madder", + "shover", + "kingwood", + "zaffir", + "copse", + "many", + "tangler", + "wirings", + "cestoses", + "carabin", + "turdine", + "garote", + "leidger", + "conodont", + "craaling", + "accurse", + "tombola", + "fishy", + "maltmen", + "linkmen", + "pranck", + "vitrail", + "collars", + "airships", + "fathom", + "exserted", + "nidering", + "inboards", + "rodeoed", + "subacid", + "reguli", + "hokum", + "vinal", + "flatlong", + "rakishly", + "shnaps", + "mittimus", + "refute", + "raupatu", + "linkster", + "asudden", + "caritas", + "chivving", + "nounless", + "allegges", + "hesperid", + "dwaumed", + "racloir", + "lungworm", + "aftersun", + "bacula", + "junto", + "coolings", + "statist", + "outsized", + "dreare", + "principe", + "lunting", + "godheads", + "toolies", + "grooly", + "manurers", + "dikers", + "toleware", + "caids", + "plaster", + "bittier", + "halakic", + "trests", + "jackstay", + "brases", + "overwary", + "crooning", + "francium", + "haafs", + "histioid", + "nastily", + "prelacy", + "rathas", + "wyes", + "patka", + "sclaffed", + "caracols", + "peptonic", + "stishies", + "libelous", + "hunky", + "squishes", + "monecian", + "madrasa", + "shicksa", + "mythises", + "jaywalks", + "subindex", + "perfecti", + "digamies", + "hunch", + "autocoid", + "victual", + "cannas", + "actuals", + "neep", + "daze", + "carl", + "kaizen", + "adorned", + "duffer", + "adz", + "outhyred", + "bumpy", + "biofilm", + "gummings", + "yakhdans", + "goatskin", + "haes", + "ermelin", + "jitter", + "thine", + "smote", + "milliare", + "isogons", + "apanage", + "nepotic", + "kart", + "turnup", + "ungotten", + "akatea", + "hominize", + "flyhand", + "scribing", + "readapt", + "overplus", + "papayas", + "forbore", + "enjoined", + "watt", + "uncini", + "signora", + "whipping", + "nalas", + "stripier", + "gecking", + "liveness", + "coedited", + "ciders", + "dequeued", + "poovy", + "precepit", + "avgases", + "boccas", + "condoes", + "traplike", + "spaer", + "sortment", + "techily", + "renvois", + "archaeal", + "crumbly", + "bruiter", + "tubfuls", + "assentor", + "soulful", + "gramps", + "swingers", + "unhived", + "dietings", + "mosks", + "satiate", + "milking", + "schlocky", + "telefilm", + "culling", + "curricle", + "curvier", + "mundungo", + "lown", + "dawties", + "withy", + "taus", + "biotech", + "yonic", + "moderne", + "bangalow", + "ephas", + "impinge", + "dobie", + "tribute", + "reverser", + "rascal", + "preens", + "ostent", + "ragwheel", + "uprest", + "abidings", + "rheobase", + "phrasy", + "koura", + "restrive", + "muriatic", + "miscut", + "oust", + "reverist", + "olfact", + "stems", + "triacs", + "corbels", + "tommed", + "echini", + "astone", + "rarking", + "dhimmi", + "spaded", + "peare", + "lecturns", + "outdrop", + "incline", + "juicer", + "labiates", + "kep", + "divisim", + "toffs", + "insults", + "pulli", + "canulate", + "leming", + "spurrier", + "califs", + "outburnt", + "tightass", + "pedipalp", + "mesnalty", + "acarines", + "flouse", + "seceding", + "poxes", + "murmurer", + "flooder", + "hireling", + "cowpie", + "lunes", + "sacra", + "ungluing", + "sewings", + "dotter", + "flockier", + "mutt", + "avowable", + "sleeving", + "tuppence", + "bet", + "lies", + "rhodiums", + "charpies", + "redwing", + "equants", + "imphees", + "feminize", + "calibres", + "quadriga", + "pandoras", + "doting", + "calvered", + "pugils", + "chesnuts", + "dagoba", + "hall", + "zugzwang", + "seers", + "nerolis", + "apays", + "bigstick", + "taggants", + "wallop", + "bluecaps", + "discards", + "tighter", + "cowbane", + "grilles", + "dogeate", + "buke", + "bract", + "fuller", + "engirded", + "gobis", + "proteid", + "bloviate", + "whot", + "adept", + "surats", + "freshing", + "suites", + "obsessor", + "erodible", + "sieger", + "blots", + "leeps", + "pennon", + "wigglers", + "forfend", + "pulsing", + "areas", + "buyoff", + "gymped", + "aquatint", + "stopt", + "confute", + "dewier", + "groining", + "missaid", + "cromorne", + "bury", + "anlaces", + "drugging", + "croupade", + "polkaed", + "noddled", + "disguise", + "sunning", + "telic", + "strayed", + "posaune", + "inclasp", + "birkier", + "volumes", + "fellah", + "rootsier", + "tauting", + "propenyl", + "enfolded", + "rhexises", + "simar", + "saddhu", + "seawives", + "fretsaw", + "forinsec", + "outgush", + "fumages", + "banditry", + "tuples", + "blisters", + "nozzer", + "messing", + "hoghood", + "snaws", + "appetise", + "parriers", + "musk", + "lats", + "puggrees", + "lavishly", + "latitats", + "caroling", + "clothes", + "jingly", + "escapado", + "evincive", + "riveret", + "imbedded", + "jettison", + "lighting", + "breenge", + "spruik", + "wawaed", + "fogs", + "scumfish", + "optimise", + "peep", + "affinal", + "pingoes", + "brands", + "cambric", + "ion", + "straight", + "rhus", + "darbies", + "outecho", + "declaws", + "exurbia", + "intends", + "mutest", + "curtly", + "riata", + "almsmen", + "redonned", + "cornea", + "reeker", + "bigging", + "unhidden", + "epically", + "bulwarks", + "zoomed", + "docks", + "cannular", + "seedbed", + "regurs", + "prescore", + "agonies", + "tritomas", + "showdown", + "enhunger", + "orc", + "hafniums", + "trykes", + "sease", + "reglued", + "gemology", + "calorize", + "lavoltas", + "foghorn", + "torminal", + "backsets", + "highway", + "twangers", + "tartuffe", + "monogamy", + "batten", + "rebozos", + "franking", + "geekdoms", + "entrench", + "gaziest", + "apter", + "bejabers", + "poufing", + "vair", + "catchup", + "picenes", + "paretic", + "nettie", + "gonia", + "paras", + "alidades", + "stooshie", + "claret", + "lentoid", + "concord", + "bisects", + "unwaning", + "futhorcs", + "sartorii", + "langspel", + "cylices", + "hieland", + "paroled", + "meadows", + "lockfast", + "grisgris", + "autarchs", + "sjambok", + "reborn", + "hassock", + "dinarchy", + "convos", + "acrogens", + "wieldier", + "vouchers", + "samiels", + "mankini", + "rafters", + "egger", + "stane", + "skellie", + "persico", + "wang", + "midiron", + "hydremia", + "eugenols", + "catastas", + "gabbing", + "foeman", + "gastric", + "dewdrop", + "genera", + "sifakas", + "quinate", + "vergency", + "lookout", + "honda", + "stridden", + "coypous", + "enviable", + "languors", + "stimes", + "oleates", + "knobble", + "washy", + "accepter", + "narking", + "dimmings", + "revisory", + "wontless", + "overplan", + "unloving", + "impactor", + "trichome", + "vetoers", + "fistic", + "vernicle", + "crousely", + "wellies", + "sownes", + "changes", + "antijam", + "logotypy", + "comedown", + "stalely", + "penk", + "glumpish", + "perfings", + "bulkily", + "ranarian", + "faraday", + "digamist", + "endzone", + "cohabit", + "skidway", + "mae", + "niobites", + "anchusas", + "hoisin", + "bronchos", + "spoons", + "gabled", + "valkyrie", + "almah", + "spirting", + "sapors", + "cauker", + "wispily", + "hexarchy", + "rests", + "gloating", + "carders", + "pixyish", + "gapes", + "wets", + "wiseguys", + "brailled", + "heydeys", + "irids", + "upriver", + "kinones", + "inertia", + "hyalin", + "dieoff", + "phengite", + "gait", + "enervate", + "wittier", + "spectre", + "addoomed", + "tanked", + "malichos", + "ungula", + "poulters", + "agazed", + "guaranty", + "runnable", + "updart", + "ranke", + "lowland", + "pyorrhea", + "leaching", + "deleaded", + "ethe", + "anarchs", + "unsprung", + "fiercely", + "kidels", + "sooey", + "bloosmed", + "linishes", + "amtman", + "relator", + "legato", + "eclectic", + "elenchs", + "impinges", + "sluicy", + "untune", + "dangles", + "uprising", + "outrowed", + "mosh", + "tented", + "pipits", + "cropful", + "benzoin", + "linseed", + "epimer", + "cundy", + "gau", + "sawbucks", + "pigsney", + "shindigs", + "updived", + "pise", + "demured", + "halakah", + "gynecium", + "shim", + "gossipy", + "loadstar", + "ply", + "saveable", + "polting", + "fusillis", + "agunah", + "dugites", + "necklets", + "dadaist", + "jarta", + "flatfeet", + "moreover", + "bibbery", + "ducks", + "righties", + "hagrode", + "rosing", + "huzzah", + "murren", + "outleapt", + "virion", + "cocaines", + "augers", + "ahind", + "tarpan", + "imposer", + "ticed", + "steeks", + "oilways", + "worst", + "galleta", + "moneran", + "hornbook", + "fifths", + "charleys", + "corybant", + "anears", + "diamides", + "pomes", + "outwells", + "abigail", + "perchers", + "mishit", + "chicha", + "sorriest", + "etalage", + "monaul", + "genie", + "coaitas", + "misology", + "upas", + "fiorin", + "attainer", + "coypus", + "hership", + "motus", + "bourd", + "podites", + "atween", + "lingas", + "saucers", + "basho", + "zocalo", + "puggry", + "girders", + "epaule", + "rises", + "smalling", + "homers", + "alif", + "meshing", + "slake", + "overlent", + "afoot", + "posers", + "svarajes", + "spaza", + "larch", + "calces", + "odorizes", + "whisk", + "ansa", + "missus", + "matzos", + "betty", + "curtsies", + "hivelike", + "argil", + "condos", + "vee", + "tristful", + "solatia", + "vartabed", + "lurching", + "cache", + "jeerings", + "matzas", + "veneer", + "soursops", + "burks", + "cayenne", + "stewpot", + "mucoidal", + "kreutzer", + "wammus", + "kisans", + "yeukiest", + "cinereas", + "bedded", + "colog", + "sluing", + "pacific", + "unisonal", + "slayer", + "irisate", + "deprived", + "unturfed", + "epimeric", + "haricots", + "lifull", + "squit", + "potbound", + "outputs", + "panto", + "pellocks", + "linguine", + "aggadah", + "sylvites", + "inlayer", + "hob", + "kippers", + "sockless", + "miniver", + "moperies", + "gabbards", + "wested", + "piney", + "clomp", + "mortgage", + "aweless", + "seadrome", + "kotow", + "trenails", + "brule", + "loutish", + "eightvos", + "sir", + "anyways", + "squamula", + "sumach", + "maybes", + "cookies", + "aquifer", + "cholas", + "euks", + "connings", + "wolly", + "culet", + "prisere", + "gadwalls", + "booays", + "securers", + "basest", + "igapo", + "bulging", + "lintless", + "handfuls", + "dummy", + "ricey", + "muntrie", + "situps", + "trepans", + "lapper", + "players", + "tonsils", + "congrues", + "rubies", + "deedless", + "wintling", + "cards", + "goops", + "aufgabe", + "siloxane", + "superhot", + "inwalls", + "sizeisms", + "panaceas", + "sirups", + "gongyo", + "vigias", + "fetus", + "friture", + "poker", + "vision", + "barmiest", + "addling", + "exuded", + "highball", + "brie", + "anchors", + "shakers", + "raik", + "siwash", + "pogey", + "lovings", + "hiragana", + "vesuvian", + "sheikdom", + "stoccata", + "tolsel", + "reread", + "vichies" +] diff --git a/package.json b/package.json index 20ff34c..df01848 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,11 @@ "hardhat": "^3.2.0", "prettier": "^3.8.1", "prettier-plugin-solidity": "^2.3.1", + "bip39": "^3.1.0", "solhint": "^6.1.0", "subset-font": "^1.7.0", "typescript": "~5.8.3", - "viem": "^2.47.6" + "viem": "^2.47.6", + "word-list-json": "^0.2.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bb8d7ab..29ee0cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@typescript-eslint/parser': specifier: ^8.57.2 version: 8.57.2(eslint@10.1.0)(typescript@5.8.3) + bip39: + specifier: ^3.1.0 + version: 3.1.0 dotenv: specifier: ^17.2.0 version: 17.3.1 @@ -65,6 +68,9 @@ importers: viem: specifier: ^2.47.6 version: 2.47.6(typescript@5.8.3)(zod@3.25.76) + word-list-json: + specifier: ^0.2.0 + version: 0.2.0 packages: @@ -785,6 +791,9 @@ packages: peerDependencies: ajv: 4.11.8 - 8 + bip39@3.1.0: + resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==} + bn.js@4.12.3: resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==} @@ -1559,6 +1568,10 @@ packages: woff2sfnt-sfnt2woff@1.0.0: resolution: {integrity: sha512-edK4COc1c1EpRfMqCZO1xJOvdUtM5dbVb9iz97rScvnTevqEB3GllnLWCmMVp1MfQBdF1DFg/11I0rSyAdS4qQ==} + word-list-json@0.2.0: + resolution: {integrity: sha512-A0ZuPMpXOjC8Wj0PxNWg5MB63AooXlGqaxCZOgr7anmDr4kEeP0arsaRRCSxahuZ3GVrd8OBZ+IBlpL6z7kb9A==} + engines: {node: '>=0.10.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -2384,6 +2397,10 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 + bip39@3.1.0: + dependencies: + '@noble/hashes': 1.8.0 + bn.js@4.12.3: {} bn.js@5.2.3: {} @@ -3195,6 +3212,8 @@ snapshots: dependencies: pako: 1.0.11 + word-list-json@0.2.0: {} + word-wrap@1.2.5: {} wrappy@1.0.2: {} diff --git a/scripts/generate-fake-mnemonic-wordlist.mjs b/scripts/generate-fake-mnemonic-wordlist.mjs new file mode 100644 index 0000000..872e75c --- /dev/null +++ b/scripts/generate-fake-mnemonic-wordlist.mjs @@ -0,0 +1,55 @@ +import { mkdirSync, writeFileSync } from "node:fs"; +import { randomInt } from "node:crypto"; +import { wordlists } from "bip39"; +import wordList from "word-list-json"; + +const OUTPUT_DIR = new URL("../assets/mnemonic/", import.meta.url); +const OUTPUT_FILE = new URL("fake-wordlist.json", OUTPUT_DIR); +const TARGET_COUNT = 2048; + +const getLengthRange = (words) => { + let min = Infinity; + let max = -Infinity; + for (const word of words) { + const len = word.length; + if (len < min) min = len; + if (len > max) max = len; + } + return { min, max }; +}; + +const bip39List = wordlists.english.map((word) => word.toLowerCase()); +const bip39Words = new Set(bip39List); +const { min: minLength, max: maxLength } = getLengthRange(bip39List); +const candidates = Array.from( + new Set( + wordList.map((word) => String(word).toLowerCase().trim()).filter(Boolean), + ), +).filter( + (word) => + /^[a-z]+$/.test(word) && + !bip39Words.has(word) && + word.length >= minLength && + word.length <= maxLength, +); + +if (candidates.length < TARGET_COUNT) { + throw new Error( + `Not enough candidate words (${candidates.length}) after filtering out BIP-39 words and enforcing length ${minLength}-${maxLength}.`, + ); +} + +const selection = candidates.slice(); +for (let i = selection.length - 1; i > 0; i -= 1) { + const j = randomInt(i + 1); + [selection[i], selection[j]] = [selection[j], selection[i]]; +} + +const chosen = selection.slice(0, TARGET_COUNT); + +mkdirSync(OUTPUT_DIR, { recursive: true }); +writeFileSync(OUTPUT_FILE, `${JSON.stringify(chosen, null, 2)}\n`, "utf8"); + +console.log( + `Wrote ${chosen.length} words to ${OUTPUT_FILE.pathname} (length ${minLength}-${maxLength}).`, +); diff --git a/scripts/render-svg-fake-mnemonic.mjs b/scripts/render-svg-fake-mnemonic.mjs new file mode 100644 index 0000000..fd2a657 --- /dev/null +++ b/scripts/render-svg-fake-mnemonic.mjs @@ -0,0 +1,120 @@ +import { network } from "hardhat"; +import { readFile, mkdir, writeFile } from "node:fs/promises"; +import { dirname } from "node:path"; +import { randomBytes } from "node:crypto"; +import { keccak256, stringToHex, toHex } from "viem"; + +const WORDLIST_PATH = new URL("../assets/mnemonic/fake-wordlist.json", import.meta.url); +const LETTERS_CHUNKS_PATH = new URL( + "../assets/fonts/caveat/Caveat-Bold.subset.chunks.json", + import.meta.url, +); +const DIGITS_CHUNKS_PATH = new URL( + "../assets/fonts/inter/Inter.subset.chunks.json", + import.meta.url, +); +const OUT_PATH = "/Users/xx/Developer/biscuit/tmp/fake-mnemonic.svg"; + +const loadWordlist = async () => { + const raw = await readFile(WORDLIST_PATH, "utf8"); + const list = JSON.parse(raw); + if (!Array.isArray(list)) { + throw new Error("fake-wordlist.json must be an array"); + } + if (list.length !== 2048) { + throw new Error(`fake-wordlist.json must have 2048 entries (got ${list.length})`); + } + return list.map((word, idx) => { + if (typeof word !== "string" || word.length === 0) { + throw new Error(`Invalid word at index ${idx}`); + } + return word; + }); +}; + +const loadChunks = async (path, label) => { + let raw; + try { + raw = await readFile(path, "utf8"); + } catch (err) { + throw new Error( + `${label} chunks not found. Run "pnpm fonts:prepare" to generate woff2 chunks.`, + { cause: err }, + ); + } + const json = JSON.parse(raw); + if (!Array.isArray(json.chunks) || json.chunks.length === 0) { + throw new Error(`${label} chunks missing or empty`); + } + return json.chunks; +}; + +const loadFontToContract = async (font, lettersChunks, digitsChunks, owner) => { + for (let i = 0; i < lettersChunks.length; i += 1) { + await font.write.addLetters([lettersChunks[i]], { account: owner.account }); + } + for (let i = 0; i < digitsChunks.length; i += 1) { + await font.write.addDigits([digitsChunks[i]], { account: owner.account }); + } +}; + +const loadWordlistToContract = async (mnemonic, wordlist, owner) => { + for (let i = 0; i < wordlist.length; i += 1) { + await mnemonic.write.setWordList([i, stringToHex(wordlist[i])], { + account: owner.account, + }); + if ((i + 1) % 256 === 0) { + console.log(`Wordlist: ${i + 1}/${wordlist.length}`); + } + } + await mnemonic.write.lockWordList({ account: owner.account }); +}; + +const main = async () => { + const wordlist = await loadWordlist(); + const lettersChunks = await loadChunks(LETTERS_CHUNKS_PATH, "Letters"); + const digitsChunks = await loadChunks(DIGITS_CHUNKS_PATH, "Digits"); + + const { viem } = await network.connect(); + const [owner] = await viem.getWalletClients(); + + const mnemonic = await viem.deployContract("Mnemonic", [owner.account.address]); + await loadWordlistToContract(mnemonic, wordlist, owner); + + const font = await viem.deployContract("BiscuitFont", [owner.account.address]); + await loadFontToContract(font, lettersChunks, digitsChunks, owner); + + const builder = await viem.deployContract("BiscuitBuilder", [ + owner.account.address, + font.address, + mnemonic.address, + ]); + + const rawSeed = randomBytes(32); + const seed = await builder.read.generateSeed([1n]); + const seedWithHashed = { + mnemonicSeed: keccak256(toHex(rawSeed)), + mnemonicStrength: seed.mnemonicStrength, + }; + + const svg = await builder.read.svg([seedWithHashed]); + + await mkdir(dirname(OUT_PATH), { recursive: true }); + await writeFile(OUT_PATH, svg, "utf8"); + + const words = await mnemonic.read.generateMnemonic([ + seedWithHashed.mnemonicStrength, + seedWithHashed.mnemonicSeed, + ]); + + console.log(`Seed (raw): 0x${rawSeed.toString("hex")}`); + console.log(`Seed (keccak256): ${seedWithHashed.mnemonicSeed}`); + console.log(`Strength: ${seedWithHashed.mnemonicStrength}`); + console.log(`Mnemonic (${words.length} words): ${words.join(" ")}`); + console.log(OUT_PATH); +}; + +main().catch((err) => { + console.error(err instanceof Error ? err.message : err); + process.exit(1); +}); From 57fe7367c64132e5e7e5000fd5b1d8905e45ab6c Mon Sep 17 00:00:00 2001 From: xt0x Date: Sun, 29 Mar 2026 06:55:43 +0900 Subject: [PATCH 3/3] style(mnemonic): format wordlist generator --- scripts/generate-fake-mnemonic-wordlist.mjs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/generate-fake-mnemonic-wordlist.mjs b/scripts/generate-fake-mnemonic-wordlist.mjs index 872e75c..ca60379 100644 --- a/scripts/generate-fake-mnemonic-wordlist.mjs +++ b/scripts/generate-fake-mnemonic-wordlist.mjs @@ -22,9 +22,7 @@ const bip39List = wordlists.english.map((word) => word.toLowerCase()); const bip39Words = new Set(bip39List); const { min: minLength, max: maxLength } = getLengthRange(bip39List); const candidates = Array.from( - new Set( - wordList.map((word) => String(word).toLowerCase().trim()).filter(Boolean), - ), + new Set(wordList.map((word) => String(word).toLowerCase().trim()).filter(Boolean)), ).filter( (word) => /^[a-z]+$/.test(word) &&