[{"data":1,"prerenderedAt":852},["ShallowReactive",2],{"navigation_docs":3,"-guide-custom":196,"-guide-custom-surround":847},[4,44],{"title":5,"path":6,"stem":7,"children":8,"icon":43},"Guide","\u002Fguide","1.guide\u002F01.index",[9,11,15,19,23,27,31,35,39],{"title":10,"path":6,"stem":7},"Getting Started",{"title":12,"path":13,"stem":14},"Registry and aliases","\u002Fguide\u002Fregistry","1.guide\u002F02.registry",{"title":16,"path":17,"stem":18},"Address validation","\u002Fguide\u002Fvalidation","1.guide\u002F03.validation",{"title":20,"path":21,"stem":22},"Identify","\u002Fguide\u002Fidentify","1.guide\u002F04.identify",{"title":24,"path":25,"stem":26},"Metadata","\u002Fguide\u002Fmetadata","1.guide\u002F05.metadata",{"title":28,"path":29,"stem":30},"CLI","\u002Fguide\u002Fcli","1.guide\u002F06.cli",{"title":32,"path":33,"stem":34},"Agents","\u002Fguide\u002Fagents","1.guide\u002F07.agents",{"title":36,"path":37,"stem":38},"Custom chains","\u002Fguide\u002Fcustom","1.guide\u002F08.custom",{"title":40,"path":41,"stem":42},"Playground","\u002Fguide\u002Fplayground","1.guide\u002F09.playground","i-lucide-book-open",{"title":45,"path":46,"stem":47,"children":48,"icon":195},"Chains","\u002Fchains","2.chains\u002F00.index",[49,51,55,59,63,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191],{"title":50,"path":46,"stem":47},"Overview",{"title":52,"path":53,"stem":54},"Ethereum","\u002Fchains\u002Fethereum","2.chains\u002F01.ethereum",{"title":56,"path":57,"stem":58},"Base","\u002Fchains\u002Fbase","2.chains\u002F02.base",{"title":60,"path":61,"stem":62},"Arbitrum One","\u002Fchains\u002Farbitrum","2.chains\u002F03.arbitrum",{"title":64,"path":65,"stem":66},"Optimism","\u002Fchains\u002Foptimism","2.chains\u002F04.optimism",{"title":68,"path":69,"stem":70},"Polygon PoS","\u002Fchains\u002Fpolygon","2.chains\u002F05.polygon",{"title":72,"path":73,"stem":74},"BNB Chain","\u002Fchains\u002Fbsc","2.chains\u002F06.bsc",{"title":76,"path":77,"stem":78},"Avalanche C-Chain","\u002Fchains\u002Favalanche","2.chains\u002F07.avalanche",{"title":80,"path":81,"stem":82},"Fantom Opera","\u002Fchains\u002Ffantom","2.chains\u002F08.fantom",{"title":84,"path":85,"stem":86},"Gnosis Chain","\u002Fchains\u002Fgnosis","2.chains\u002F09.gnosis",{"title":88,"path":89,"stem":90},"Linea","\u002Fchains\u002Flinea","2.chains\u002F10.linea",{"title":92,"path":93,"stem":94},"zkSync Era","\u002Fchains\u002Fzksync","2.chains\u002F11.zksync",{"title":96,"path":97,"stem":98},"Scroll","\u002Fchains\u002Fscroll","2.chains\u002F12.scroll",{"title":100,"path":101,"stem":102},"Berachain","\u002Fchains\u002Fberachain","2.chains\u002F13.berachain",{"title":104,"path":105,"stem":106},"Bitcoin","\u002Fchains\u002Fbitcoin","2.chains\u002F14.bitcoin",{"title":108,"path":109,"stem":110},"Litecoin","\u002Fchains\u002Flitecoin","2.chains\u002F15.litecoin",{"title":112,"path":113,"stem":114},"Pepecoin","\u002Fchains\u002Fpepecoin","2.chains\u002F16.pepecoin",{"title":116,"path":117,"stem":118},"eCash","\u002Fchains\u002Fecash","2.chains\u002F17.ecash",{"title":120,"path":121,"stem":122},"Cardano","\u002Fchains\u002Fcardano","2.chains\u002F18.cardano",{"title":124,"path":125,"stem":126},"Solana","\u002Fchains\u002Fsolana","2.chains\u002F19.solana",{"title":128,"path":129,"stem":130},"Stellar","\u002Fchains\u002Fstellar","2.chains\u002F20.stellar",{"title":132,"path":133,"stem":134},"XRP Ledger","\u002Fchains\u002Fxrpl","2.chains\u002F21.xrpl",{"title":136,"path":137,"stem":138},"Aptos","\u002Fchains\u002Faptos","2.chains\u002F22.aptos",{"title":140,"path":141,"stem":142},"Sui","\u002Fchains\u002Fsui","2.chains\u002F23.sui",{"title":144,"path":145,"stem":146},"TON (The Open Network)","\u002Fchains\u002Fton","2.chains\u002F24.ton",{"title":148,"path":149,"stem":150},"TRON","\u002Fchains\u002Ftron","2.chains\u002F25.tron",{"title":152,"path":153,"stem":154},"Octra","\u002Fchains\u002Foctra","2.chains\u002F26.octra",{"title":156,"path":157,"stem":158},"Arweave","\u002Fchains\u002Farweave","2.chains\u002F27.arweave",{"title":160,"path":161,"stem":162},"Monero","\u002Fchains\u002Fmonero","2.chains\u002F28.monero",{"title":164,"path":165,"stem":166},"Decred","\u002Fchains\u002Fdecred","2.chains\u002F29.decred",{"title":168,"path":169,"stem":170},"Arc","\u002Fchains\u002Farc","2.chains\u002F30.arc",{"title":172,"path":173,"stem":174},"Dogecoin","\u002Fchains\u002Fdogecoin","2.chains\u002F31.dogecoin",{"title":176,"path":177,"stem":178},"Bitcoin Cash","\u002Fchains\u002Fbitcoincash","2.chains\u002F32.bitcoincash",{"title":180,"path":181,"stem":182},"Bitcoin SV","\u002Fchains\u002Fbitcoinsv","2.chains\u002F33.bitcoinsv",{"title":184,"path":185,"stem":186},"Bitcoin Gold","\u002Fchains\u002Fbitcoingold","2.chains\u002F34.bitcoingold",{"title":188,"path":189,"stem":190},"Dash","\u002Fchains\u002Fdash","2.chains\u002F35.dash",{"title":192,"path":193,"stem":194},"Zcash","\u002Fchains\u002Fzcash","2.chains\u002F36.zcash","i-lucide-link",{"id":197,"title":36,"body":198,"description":840,"extension":841,"links":842,"meta":843,"navigation":278,"path":37,"seo":845,"stem":38,"__hash__":846},"docs\u002F1.guide\u002F08.custom.md",{"type":199,"value":200,"toc":834},"minimark",[201,206,223,558,622,644,648,788,792,803,807,830],[202,203,205],"h2",{"id":204},"one-class-one-file","One class, one file",[207,208,209,210,214,215,218,219,222],"p",{},"Every built-in is a concrete class extending the exported abstract ",[211,212,213],"code",{},"Chain",", or ",[211,216,217],{},"EVM"," and ",[211,220,221],{},"Move"," when the address format is theirs. Yours is the same shape:",[224,225,231],"pre",{"className":226,"code":227,"filename":228,"language":229,"meta":230,"style":230},"language-ts shiki shiki-themes chains chains chains","import { Chain, InvalidAddressError, register } from \"@agntn\u002Fchains\";\nimport type { ChainKey, ChainType } from \"@agntn\u002Fchains\";\n\n\u002F** The shape of a Nano account. Its checksum stays unchecked here. *\u002F\nconst ADDRESS = \u002F^nano_[13][13456789abcdefghijkmnopqrstuwxyz]{59}$\u002F;\n\nclass Nano extends Chain {\n  static readonly key = \"nano\" as ChainKey;\n  readonly type = \"nano\" as ChainType;\n  readonly name = \"Nano\";\n  readonly symbol = \"XNO\";\n  override readonly decimals = 30;\n  readonly explorer = \"https:\u002F\u002Fnanexplorer.com\u002Fnano\";\n  override readonly bip44 = 165;\n\n  override assertAddress(address: string): string {\n    if (!ADDRESS.test(address)) throw new InvalidAddressError(this.key, address);\n    return address;\n  }\n}\n\nregister(Nano);\n","nano.ts","ts","",[211,232,233,256,273,280,287,316,321,337,362,382,397,412,428,443,458,463,490,523,532,538,544,549],{"__ignoreMap":230},[234,235,238,242,246,249,253],"span",{"class":236,"line":237},"line",1,[234,239,241],{"class":240},"skH_V","import",[234,243,245],{"class":244},"s38Sx"," { Chain, InvalidAddressError, register } ",[234,247,248],{"class":240},"from",[234,250,252],{"class":251},"shU9J"," \"@agntn\u002Fchains\"",[234,254,255],{"class":244},";\n",[234,257,259,261,264,267,269,271],{"class":236,"line":258},2,[234,260,241],{"class":240},[234,262,263],{"class":240}," type",[234,265,266],{"class":244}," { ChainKey, ChainType } ",[234,268,248],{"class":240},[234,270,252],{"class":251},[234,272,255],{"class":244},[234,274,276],{"class":236,"line":275},3,[234,277,279],{"emptyLinePlaceholder":278},true,"\n",[234,281,283],{"class":236,"line":282},4,[234,284,286],{"class":285},"scIB-","\u002F** The shape of a Nano account. Its checksum stays unchecked here. *\u002F\n",[234,288,290,293,296,299,302,305,308,311,314],{"class":236,"line":289},5,[234,291,292],{"class":240},"const",[234,294,295],{"class":244}," ADDRESS ",[234,297,298],{"class":240},"=",[234,300,301],{"class":251}," \u002F",[234,303,304],{"class":240},"^",[234,306,307],{"class":251},"nano_[13][13456789abcdefghijkmnopqrstuwxyz]",[234,309,310],{"class":240},"{59}$",[234,312,313],{"class":251},"\u002F",[234,315,255],{"class":244},[234,317,319],{"class":236,"line":318},6,[234,320,279],{"emptyLinePlaceholder":278},[234,322,324,327,331,334],{"class":236,"line":323},7,[234,325,326],{"class":240},"class",[234,328,330],{"class":329},"sK71F"," Nano",[234,332,333],{"class":240}," extends",[234,335,336],{"class":244}," Chain {\n",[234,338,340,343,346,349,351,354,357,360],{"class":236,"line":339},8,[234,341,342],{"class":240},"  static",[234,344,345],{"class":240}," readonly",[234,347,348],{"class":244}," key ",[234,350,298],{"class":240},[234,352,353],{"class":251}," \"nano\"",[234,355,356],{"class":240}," as",[234,358,359],{"class":329}," ChainKey",[234,361,255],{"class":244},[234,363,365,368,371,373,375,377,380],{"class":236,"line":364},9,[234,366,367],{"class":240},"  readonly",[234,369,370],{"class":244}," type ",[234,372,298],{"class":240},[234,374,353],{"class":251},[234,376,356],{"class":240},[234,378,379],{"class":329}," ChainType",[234,381,255],{"class":244},[234,383,385,387,390,392,395],{"class":236,"line":384},10,[234,386,367],{"class":240},[234,388,389],{"class":244}," name ",[234,391,298],{"class":240},[234,393,394],{"class":251}," \"Nano\"",[234,396,255],{"class":244},[234,398,400,402,405,407,410],{"class":236,"line":399},11,[234,401,367],{"class":240},[234,403,404],{"class":244}," symbol ",[234,406,298],{"class":240},[234,408,409],{"class":251}," \"XNO\"",[234,411,255],{"class":244},[234,413,415,418,420,423,425],{"class":236,"line":414},12,[234,416,417],{"class":240},"  override",[234,419,345],{"class":240},[234,421,422],{"class":244}," decimals ",[234,424,298],{"class":240},[234,426,427],{"class":244}," 30;\n",[234,429,431,433,436,438,441],{"class":236,"line":430},13,[234,432,367],{"class":240},[234,434,435],{"class":244}," explorer ",[234,437,298],{"class":240},[234,439,440],{"class":251}," \"https:\u002F\u002Fnanexplorer.com\u002Fnano\"",[234,442,255],{"class":244},[234,444,446,448,450,453,455],{"class":236,"line":445},14,[234,447,417],{"class":240},[234,449,345],{"class":240},[234,451,452],{"class":244}," bip44 ",[234,454,298],{"class":240},[234,456,457],{"class":244}," 165;\n",[234,459,461],{"class":236,"line":460},15,[234,462,279],{"emptyLinePlaceholder":278},[234,464,466,468,471,474,477,480,483,485,487],{"class":236,"line":465},16,[234,467,417],{"class":240},[234,469,470],{"class":329}," assertAddress",[234,472,473],{"class":244},"(address",[234,475,476],{"class":240},":",[234,478,479],{"class":329}," string",[234,481,482],{"class":244},")",[234,484,476],{"class":240},[234,486,479],{"class":329},[234,488,489],{"class":244}," {\n",[234,491,493,496,499,502,505,508,511,514,517,520],{"class":236,"line":492},17,[234,494,495],{"class":240},"    if",[234,497,498],{"class":244}," (",[234,500,501],{"class":240},"!",[234,503,504],{"class":244},"ADDRESS.",[234,506,507],{"class":329},"test",[234,509,510],{"class":244},"(address)) ",[234,512,513],{"class":240},"throw",[234,515,516],{"class":240}," new",[234,518,519],{"class":329}," InvalidAddressError",[234,521,522],{"class":244},"(this.key, address);\n",[234,524,526,529],{"class":236,"line":525},18,[234,527,528],{"class":240},"    return",[234,530,531],{"class":244}," address;\n",[234,533,535],{"class":236,"line":534},19,[234,536,537],{"class":244},"  }\n",[234,539,541],{"class":236,"line":540},20,[234,542,543],{"class":244},"}\n",[234,545,547],{"class":236,"line":546},21,[234,548,279],{"emptyLinePlaceholder":278},[234,550,552,555],{"class":236,"line":551},22,[234,553,554],{"class":329},"register",[234,556,557],{"class":244},"(Nano);\n",[224,559,561],{"className":226,"code":560,"language":229,"meta":230,"style":230},"import \".\u002Fnano\";\nimport { create, getChain, identify } from \"@agntn\u002Fchains\";\n\ngetChain(\"nano\").name; \u002F\u002F \"Nano\"\nidentify(\"nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3\").matches[0]?.key; \u002F\u002F \"nano\"\n",[211,562,563,572,585,589,606],{"__ignoreMap":230},[234,564,565,567,570],{"class":236,"line":237},[234,566,241],{"class":240},[234,568,569],{"class":251}," \".\u002Fnano\"",[234,571,255],{"class":244},[234,573,574,576,579,581,583],{"class":236,"line":258},[234,575,241],{"class":240},[234,577,578],{"class":244}," { create, getChain, identify } ",[234,580,248],{"class":240},[234,582,252],{"class":251},[234,584,255],{"class":244},[234,586,587],{"class":236,"line":275},[234,588,279],{"emptyLinePlaceholder":278},[234,590,591,594,597,600,603],{"class":236,"line":282},[234,592,593],{"class":329},"getChain",[234,595,596],{"class":244},"(",[234,598,599],{"class":251},"\"nano\"",[234,601,602],{"class":244},").name; ",[234,604,605],{"class":285},"\u002F\u002F \"Nano\"\n",[234,607,608,611,613,616,619],{"class":236,"line":289},[234,609,610],{"class":329},"identify",[234,612,596],{"class":244},[234,614,615],{"class":251},"\"nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3\"",[234,617,618],{"class":244},").matches[0]?.key; ",[234,620,621],{"class":285},"\u002F\u002F \"nano\"\n",[207,623,624,625,218,628,631,632,635,636,639,640,643],{},"Two casts, and they are the honest part of this page. ",[211,626,627],{},"ChainKey",[211,629,630],{},"ChainType"," are closed unions of the built-in values, so a new key doesn't type check without ",[211,633,634],{},"as ChainKey",", and ",[211,637,638],{},"create(\"nano\")"," wants the same cast. ",[211,641,642],{},"getChain(\"nano\")"," takes a plain string and needs none. The unions exist so a typo in a key is a compile error inside the package; the price is paid once, in your class.",[202,645,647],{"id":646},"the-contract","The contract",[649,650,651,665,703,716,735,756,776],"ul",{},[652,653,654,657,658,660,661,664],"li",{},[211,655,656],{},"static readonly key"," is what ",[211,659,554],{}," files the class under and what ",[211,662,663],{},"chain.key"," returns. Lowercase, the chain's name rather than its ticker. Registering the same key again replaces the class.",[652,666,667,670,671,670,674,218,677,680,681,670,684,670,687,670,690,670,693,670,696,218,699,702],{},[211,668,669],{},"name",", ",[211,672,673],{},"symbol",[211,675,676],{},"type",[211,678,679],{},"explorer"," are required. ",[211,682,683],{},"decimals",[211,685,686],{},"bip44",[211,688,689],{},"chainId",[211,691,692],{},"caip2",[211,694,695],{},"magic",[211,697,698],{},"pow",[211,700,701],{},"rpcDefault"," are optional and mean unknown when left out, never a default.",[652,704,705,708,709,712,713,715],{},[211,706,707],{},"assertAddress"," returns the address or throws ",[211,710,711],{},"InvalidAddressError(this.key, address)",", with the rule that failed as an optional third argument when you can tell. Throw that class and nothing else for a bad address, because ",[211,714,610],{}," counts only that as a miss and lets any other throw come back out as a bug.",[652,717,718,719,218,721,724,725,728,729,635,732,734],{},"Skip ",[211,720,707],{},[211,722,723],{},"validatesAddress"," says ",[211,726,727],{},"false",", the base method throws ",[211,730,731],{},"AddressValidationUnsupportedError",[211,733,610],{}," lists your chain as unchecked rather than pretending it said no.",[652,736,737,740,741,744,745,747,748,751,752,755],{},[211,738,739],{},"decodeAddress"," comes free unless you extend ",[211,742,743],{},"UTXO",". It runs your ",[211,746,707],{}," and answers ",[211,749,750],{},"account",". A UTXO address pays to some script, though, and the base class won't guess which. It throws ",[211,753,754],{},"AddressDecodingUnsupportedError"," until you override it with the kind and payload.",[652,757,758,761,762,765,766,724,769,771,772,775],{},[211,759,760],{},"assertTxid"," is optional the same way. Override it and throw ",[211,763,764],{},"InvalidTxidError",", with the reason as the third argument when you can tell, or skip it and ",[211,767,768],{},"validatesTxid",[211,770,727],{},". ",[211,773,774],{},"class Mine extends UTXO"," gets the 64 hex digit check for free.",[652,777,778,779,782,783,670,785,787],{},"An EVM chain is ",[211,780,781],{},"class Mine extends EVM"," with ",[211,784,689],{},[211,786,692],{}," and the rest. Both format checks come with the family.",[202,789,791],{"id":790},"decode-when-you-can","Decode when you can",[207,793,794,795,798,799,802],{},"A regex is fine when the width is the whole format, as it is for Octra. When the format is Base58Check with a known byte length, decode and look at the bytes: a character window takes neighbouring chains and half the typos. The built-ins are the reference, ",[211,796,797],{},"src\u002Fchains\u002Ftron.ts"," is the short one and ",[211,800,801],{},"src\u002Fchains\u002Fcardano.ts"," the long one.",[202,804,806],{"id":805},"where-it-shows-up","Where it shows up",[207,808,809,810,670,813,816,817,819,820,822,823,218,826,829],{},"Once the module is imported, the chain is in ",[211,811,812],{},"chains()",[211,814,815],{},"has()"," says true, ",[211,818,593],{}," finds it by key and by display name, ",[211,821,610],{}," asks it like any other. The CLI and the MCP server only load the built-ins. To use a custom chain there you build your own binary around ",[211,824,825],{},"create",[211,827,828],{},"createMcpServer",". There's no plugin path, and I'd rather say so than invent one that half works.",[831,832,833],"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 .scIB-, html code.shiki .scIB-{--shiki-light:var(--shiki-token-comment);--shiki-default:var(--shiki-token-comment);--shiki-dark:var(--shiki-token-comment)}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 .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":230,"searchDepth":258,"depth":258,"links":835},[836,837,838,839],{"id":204,"depth":258,"text":205},{"id":646,"depth":258,"text":647},{"id":790,"depth":258,"text":791},{"id":805,"depth":258,"text":806},"Extend the abstract Chain with a key and a validator and register the class. From then on the registry treats it like a built-in.","md",null,{"icon":844},"i-lucide-plus",{"title":36,"description":840},"EhKOXJLv5XdejbhLI29MWLmGtV44ArF3BwUCe_lQRdk",[848,850],{"title":32,"path":33,"stem":34,"description":849,"children":-1},"The same five tools over MCP and the Pi and OMP extensions. What the text carries and what sets isError. What a model can't hand the process.",{"title":40,"path":41,"stem":42,"description":851,"children":-1},"The page behind chains.agntn.dev\u002Fplayground runs the library in your browser. What it can tell you and what it can't.",1791199047104]