[{"data":1,"prerenderedAt":608},["ShallowReactive",2],{"navigation_docs":3,"-guide-checksums":128,"-guide-checksums-surround":603},[4,40],{"title":5,"path":6,"stem":7,"children":8,"icon":39},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19,23,27,31,35],{"title":10,"path":6,"stem":7},"Getting Started",{"title":12,"path":13,"stem":14},"Encoding and Decoding","\u002Fguide\u002Fencoding","1.guide\u002F02.encoding",{"title":16,"path":17,"stem":18},"Checksums","\u002Fguide\u002Fchecksums","1.guide\u002F03.checksums",{"title":20,"path":21,"stem":22},"Identify","\u002Fguide\u002Fidentify","1.guide\u002F04.identify",{"title":24,"path":25,"stem":26},"CLI","\u002Fguide\u002Fcli","1.guide\u002F05.cli",{"title":28,"path":29,"stem":30},"Agents","\u002Fguide\u002Fagents","1.guide\u002F06.agents",{"title":32,"path":33,"stem":34},"Custom Encodings","\u002Fguide\u002Fcustom","1.guide\u002F07.custom",{"title":36,"path":37,"stem":38},"Playground","\u002Fguide\u002Fplayground","1.guide\u002F08.playground","i-lucide-book-open",{"title":41,"path":42,"stem":43,"children":44,"icon":127},"Encodings","\u002Fencodings","2.encodings\u002F00.index",[45,47,51,55,59,63,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123],{"title":46,"path":42,"stem":43},"Every encoding",{"title":48,"path":49,"stem":50},"Binary","\u002Fencodings\u002Fbinary","2.encodings\u002F01.binary",{"title":52,"path":53,"stem":54},"Hex","\u002Fencodings\u002Fhex","2.encodings\u002F02.hex",{"title":56,"path":57,"stem":58},"Base32","\u002Fencodings\u002Fbase32","2.encodings\u002F03.base32",{"title":60,"path":61,"stem":62},"Base32hex","\u002Fencodings\u002Fbase32hex","2.encodings\u002F04.base32hex",{"title":64,"path":65,"stem":66},"Crockford's Base32","\u002Fencodings\u002Fbase32-crockford","2.encodings\u002F05.base32-crockford",{"title":68,"path":69,"stem":70},"z-base-32","\u002Fencodings\u002Fz-base-32","2.encodings\u002F06.z-base-32",{"title":72,"path":73,"stem":74},"Base45","\u002Fencodings\u002Fbase45","2.encodings\u002F07.base45",{"title":76,"path":77,"stem":78},"Base58","\u002Fencodings\u002Fbase58","2.encodings\u002F08.base58",{"title":80,"path":81,"stem":82},"Base58Check","\u002Fencodings\u002Fbase58check","2.encodings\u002F09.base58check",{"title":84,"path":85,"stem":86},"Base58 (Flickr)","\u002Fencodings\u002Fbase58-flickr","2.encodings\u002F10.base58-flickr",{"title":88,"path":89,"stem":90},"Base58 (Ripple)","\u002Fencodings\u002Fbase58-ripple","2.encodings\u002F11.base58-ripple",{"title":92,"path":93,"stem":94},"Base64","\u002Fencodings\u002Fbase64","2.encodings\u002F12.base64",{"title":96,"path":97,"stem":98},"Base64url","\u002Fencodings\u002Fbase64url","2.encodings\u002F13.base64url",{"title":100,"path":101,"stem":102},"Ascii85","\u002Fencodings\u002Fascii85","2.encodings\u002F14.ascii85",{"title":104,"path":105,"stem":106},"Z85","\u002Fencodings\u002Fz85","2.encodings\u002F15.z85",{"title":108,"path":109,"stem":110},"basE91","\u002Fencodings\u002Fbase91","2.encodings\u002F16.base91",{"title":112,"path":113,"stem":114},"Bech32","\u002Fencodings\u002Fbech32","2.encodings\u002F17.bech32",{"title":116,"path":117,"stem":118},"Bech32m","\u002Fencodings\u002Fbech32m","2.encodings\u002F18.bech32m",{"title":120,"path":121,"stem":122},"uuencode","\u002Fencodings\u002Fuuencode","2.encodings\u002F19.uuencode",{"title":124,"path":125,"stem":126},"Quoted-Printable","\u002Fencodings\u002Fquoted-printable","2.encodings\u002F20.quoted-printable","i-lucide-library",{"id":129,"title":16,"body":130,"description":597,"extension":598,"links":599,"meta":600,"navigation":185,"path":17,"seo":601,"stem":18,"__hash__":602},"docs\u002F1.guide\u002F03.checksums.md",{"type":131,"value":132,"toc":591},"minimark",[133,137,140,144,147,219,234,242,260,274,278,285,366,376,382,389,393,396,461,464,491,495,502,564,580,587],[134,135,136],"p",{},"Most encodings will decode a typo without blinking. Swap two base64 characters and you get different bytes, no error, no warning. Fine for a data URL. Not fine for an address you're about to send money to.",[134,138,139],{},"Three encodings here carry a checksum and check it every time you decode.",[141,142,80],"h2",{"id":143},"base58check",[134,145,146],{},"Bitcoin's form for addresses, WIF keys and extended keys. The payload, then the first four bytes of its double SHA-256, all in base58.",[148,149,154],"pre",{"className":150,"code":151,"language":152,"meta":153,"style":153},"language-ts shiki shiki-themes encodings encodings encodings","import { base58check, hex } from \"@agntn\u002Fencodings\";\n\nhex.encode(base58check.decode(\"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa\"));\n\u002F\u002F \"0062e907b15cbf27d5425399ebf6f0fb50ebb88f18\"\n","ts","",[155,156,157,180,187,212],"code",{"__ignoreMap":153},[158,159,162,166,170,173,177],"span",{"class":160,"line":161},"line",1,[158,163,165],{"class":164},"skH_V","import",[158,167,169],{"class":168},"s38Sx"," { base58check, hex } ",[158,171,172],{"class":164},"from",[158,174,176],{"class":175},"shU9J"," \"@agntn\u002Fencodings\"",[158,178,179],{"class":168},";\n",[158,181,183],{"class":160,"line":182},2,[158,184,186],{"emptyLinePlaceholder":185},true,"\n",[158,188,190,193,197,200,203,206,209],{"class":160,"line":189},3,[158,191,192],{"class":168},"hex.",[158,194,196],{"class":195},"sK71F","encode",[158,198,199],{"class":168},"(base58check.",[158,201,202],{"class":195},"decode",[158,204,205],{"class":168},"(",[158,207,208],{"class":175},"\"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa\"",[158,210,211],{"class":168},"));\n",[158,213,215],{"class":160,"line":214},4,[158,216,218],{"class":217},"scIB-","\u002F\u002F \"0062e907b15cbf27d5425399ebf6f0fb50ebb88f18\"\n",[134,220,221,222,225,226,229,230,233],{},"That's the genesis block's address. One byte of version, ",[155,223,224],{},"0x00"," for mainnet P2PKH. Then the 20-byte HASH160 of Satoshi's key. Now change the last character from ",[155,227,228],{},"a"," to ",[155,231,232],{},"b",". What happens?",[148,235,240],{"className":236,"code":238,"language":239,"meta":153},[237],"language-text","base58check: checksum does not match\n","text",[155,241,238],{"__ignoreMap":153},[134,243,244,245,248,249,252,253,259],{},"It throws ",[155,246,247],{},"ChecksumError",", a subclass of ",[155,250,251],{},"DecodeError",". Catch the one you care about. The version bytes stay in the payload. This codec checks the checksum and nothing else. Which version means which network? That's ",[228,254,258],{"href":255,"rel":256},"https:\u002F\u002Fkeys.agntn.dev",[257],"nofollow","@agntn\u002Fkeys"," territory.",[134,261,262,263,266,267,270,271,273],{},"A WIF key decodes the same way. Private key 1, compressed, is ",[155,264,265],{},"80",", then 31 zero bytes and ",[155,268,269],{},"01",", then one more ",[155,272,269],{}," that says \"compressed\". Thirty-four bytes. An xpub is seventy-eight.",[141,275,277],{"id":276},"bech32-and-bech32m","Bech32 and bech32m",[134,279,280,281,284],{},"A prefix, a ",[155,282,283],{},"1",", then 5-bit words and six characters of BCH checksum. Lowercase or uppercase, never mixed. The checksum catches any four wrong characters, which is better than base58 ever did.",[148,286,288],{"className":150,"code":287,"language":152,"meta":153,"style":153},"import { bech32 } from \"@agntn\u002Fencodings\";\n\nbech32.encode(\"test\", new TextEncoder().encode(\"gm\"));\n\u002F\u002F \"test1vaks69jerm\"\nbech32.decode(\"test1vaks69jerm\");\n\u002F\u002F { prefix: \"test\", bytes: Uint8Array [103, 109] }\n",[155,289,290,303,307,340,345,360],{"__ignoreMap":153},[158,291,292,294,297,299,301],{"class":160,"line":161},[158,293,165],{"class":164},[158,295,296],{"class":168}," { bech32 } ",[158,298,172],{"class":164},[158,300,176],{"class":175},[158,302,179],{"class":168},[158,304,305],{"class":160,"line":182},[158,306,186],{"emptyLinePlaceholder":185},[158,308,309,312,314,316,319,322,325,328,331,333,335,338],{"class":160,"line":189},[158,310,311],{"class":168},"bech32.",[158,313,196],{"class":195},[158,315,205],{"class":168},[158,317,318],{"class":175},"\"test\"",[158,320,321],{"class":168},", ",[158,323,324],{"class":164},"new",[158,326,327],{"class":195}," TextEncoder",[158,329,330],{"class":168},"().",[158,332,196],{"class":195},[158,334,205],{"class":168},[158,336,337],{"class":175},"\"gm\"",[158,339,211],{"class":168},[158,341,342],{"class":160,"line":214},[158,343,344],{"class":217},"\u002F\u002F \"test1vaks69jerm\"\n",[158,346,348,350,352,354,357],{"class":160,"line":347},5,[158,349,311],{"class":168},[158,351,202],{"class":195},[158,353,205],{"class":168},[158,355,356],{"class":175},"\"test1vaks69jerm\"",[158,358,359],{"class":168},");\n",[158,361,363],{"class":160,"line":362},6,[158,364,365],{"class":217},"\u002F\u002F { prefix: \"test\", bytes: Uint8Array [103, 109] }\n",[134,367,368,369,371,372,375],{},"Bech32m is the same thing with a different constant in the checksum. Why change it? Bech32 had a quiet flaw. When the last character is ",[155,370,134],{},", you can add or drop ",[155,373,374],{},"q"," characters right before it. The old checksum still passes. Feed one variant's text to the other and the error tells you.",[148,377,380],{"className":378,"code":379,"language":239,"meta":153},[237],"bech32: checksum is bech32m's\n",[155,381,379],{"__ignoreMap":153},[134,383,384,385,388],{},"Strings over 90 characters are rejected by default, like BIP173 says. Lightning invoices are longer. Pass a ",[155,386,387],{},"limit"," when you mean it.",[141,390,392],{"id":391},"segwit-addresses","Segwit addresses",[134,394,395],{},"A segwit address is bech32 with one extra rule. The first word is the witness version, the rest is the program. Version 0 uses bech32 and a 20 or 32-byte program. Versions 1 to 16 use bech32m. Taproot is version 1.",[148,397,399],{"className":150,"code":398,"language":152,"meta":153,"style":153},"import { segwit, hex } from \"@agntn\u002Fencodings\";\n\nconst address = segwit.decode(\"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0\");\naddress.version;              \u002F\u002F 1\nhex.encode(address.program);  \u002F\u002F \"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"\n",[155,400,401,414,418,441,449],{"__ignoreMap":153},[158,402,403,405,408,410,412],{"class":160,"line":161},[158,404,165],{"class":164},[158,406,407],{"class":168}," { segwit, hex } ",[158,409,172],{"class":164},[158,411,176],{"class":175},[158,413,179],{"class":168},[158,415,416],{"class":160,"line":182},[158,417,186],{"emptyLinePlaceholder":185},[158,419,420,423,426,429,432,434,436,439],{"class":160,"line":189},[158,421,422],{"class":164},"const",[158,424,425],{"class":168}," address ",[158,427,428],{"class":164},"=",[158,430,431],{"class":168}," segwit.",[158,433,202],{"class":195},[158,435,205],{"class":168},[158,437,438],{"class":175},"\"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0\"",[158,440,359],{"class":168},[158,442,443,446],{"class":160,"line":214},[158,444,445],{"class":168},"address.version;              ",[158,447,448],{"class":217},"\u002F\u002F 1\n",[158,450,451,453,455,458],{"class":160,"line":347},[158,452,192],{"class":168},[158,454,196],{"class":195},[158,456,457],{"class":168},"(address.program);  ",[158,459,460],{"class":217},"\u002F\u002F \"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"\n",[134,462,463],{},"Recognize that program? It's the x coordinate of the secp256k1 generator, and the whole address is one of BIP350's test vectors. A real Taproot address tweaks its key first, so don't go looking for coins there.",[134,465,466,467,470,471,474,475,478,479,482,483,486,487,490],{},"The registry does this for you. ",[155,468,469],{},"decode(\"bech32\", …)"," on a valid segwit address returns the program as ",[155,472,473],{},"bytes"," and ",[155,476,477],{},"witnessVersion"," in ",[155,480,481],{},"details",". On anything else, a Nostr ",[155,484,485],{},"npub"," say, it returns the bytes the words carry. A version 0 address handed to ",[155,488,489],{},"bech32m"," fails, because that's exactly the mix-up bech32m exists to catch.",[141,492,494],{"id":493},"just-the-words","Just the words",[134,496,497,498,501],{},"Some formats borrow bech32's alphabet and its bit shuffle, then bring their own checksum. CashAddr does that with a 40-bit one. So ",[155,499,500],{},"bech32.decode"," is no help there. What you want is the regrouping alone, 8-bit bytes into 5-bit words and back.",[148,503,505],{"className":150,"code":504,"language":152,"meta":153,"style":153},"import { fromWords, toWords } from \"@agntn\u002Fencodings\u002Fbech32\";\n\ntoWords(new Uint8Array([0xff]));  \u002F\u002F [31, 28]\nfromWords([31, 28]);              \u002F\u002F Uint8Array [255]\nfromWords([31, 29]);              \u002F\u002F throws \"bech32: padding bits after the last byte are not zero\"\n",[155,506,507,521,525,543,554],{"__ignoreMap":153},[158,508,509,511,514,516,519],{"class":160,"line":161},[158,510,165],{"class":164},[158,512,513],{"class":168}," { fromWords, toWords } ",[158,515,172],{"class":164},[158,517,518],{"class":175}," \"@agntn\u002Fencodings\u002Fbech32\"",[158,520,179],{"class":168},[158,522,523],{"class":160,"line":182},[158,524,186],{"emptyLinePlaceholder":185},[158,526,527,530,532,534,537,540],{"class":160,"line":189},[158,528,529],{"class":195},"toWords",[158,531,205],{"class":168},[158,533,324],{"class":164},[158,535,536],{"class":195}," Uint8Array",[158,538,539],{"class":168},"([0xff]));  ",[158,541,542],{"class":217},"\u002F\u002F [31, 28]\n",[158,544,545,548,551],{"class":160,"line":214},[158,546,547],{"class":195},"fromWords",[158,549,550],{"class":168},"([31, 28]);              ",[158,552,553],{"class":217},"\u002F\u002F Uint8Array [255]\n",[158,555,556,558,561],{"class":160,"line":347},[158,557,547],{"class":195},[158,559,560],{"class":168},"([31, 29]);              ",[158,562,563],{"class":217},"\u002F\u002F throws \"bech32: padding bits after the last byte are not zero\"\n",[134,565,566,568,569,571,572,575,576,579],{},[155,567,547],{}," keeps BIP173's rule. At most four bits of padding, all of them zero, or you get a ",[155,570,251],{},". Just checking whether some words spell bytes at all? ",[155,573,574],{},"fromWordsUnsafe"," returns ",[155,577,578],{},"undefined"," instead of throwing, and that's what an address validator wants anyway.",[134,581,582,583,586],{},"All three come from ",[155,584,585],{},"@agntn\u002Fencodings\u002Fbech32"," only. The root import keeps to whole encodings.",[588,589,590],"style",{},"html pre.shiki code .skH_V, html code.shiki .skH_V{--shiki-light:var(--shiki-token-keyword);--shiki-default:var(--shiki-token-keyword);--shiki-dark:var(--shiki-token-keyword)}html pre.shiki code .s38Sx, html code.shiki .s38Sx{--shiki-light:var(--ui-text-highlighted);--shiki-default:var(--ui-text-highlighted);--shiki-dark:var(--ui-text-highlighted)}html pre.shiki code .shU9J, html code.shiki .shU9J{--shiki-light:var(--shiki-token-string);--shiki-default:var(--shiki-token-string);--shiki-dark:var(--shiki-token-string)}html pre.shiki code .sK71F, html code.shiki .sK71F{--shiki-light:var(--shiki-token-function);--shiki-default:var(--shiki-token-function);--shiki-dark:var(--shiki-token-function)}html pre.shiki code .scIB-, html code.shiki .scIB-{--shiki-light:var(--shiki-token-comment);--shiki-default:var(--shiki-token-comment);--shiki-dark:var(--shiki-token-comment)}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":153,"searchDepth":182,"depth":182,"links":592},[593,594,595,596],{"id":143,"depth":182,"text":80},{"id":276,"depth":182,"text":277},{"id":391,"depth":182,"text":392},{"id":493,"depth":182,"text":494},"Base58Check and bech32 and bech32m verify themselves on decode. A segwit address comes back as its version and program","md",null,{},{"title":16,"description":597},"Krzlm39WSM2Ywd1J96JjFmrjAqLBGnNVY7jt3jfgH5o",[604,606],{"title":12,"path":13,"stem":14,"description":605,"children":-1},"Two calls by name, a codec object per encoding and a subpath per family. Strings are UTF-8 and bytes stay bytes",{"title":20,"path":21,"stem":22,"description":607,"children":-1},"Rank the encodings a string decodes in. Each score comes with the reasons behind it",1790959571669]