(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3152],{2990:function(e,s,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/services/indexer",function(){return n(174)}])},8986:function(e,s,n){"use strict";n.d(s,{C:function(){return a}});var t=n(7505),r=n(7765),i=n(4737),l=n.n(i);function a(e){let{children:s}=e,n=(0,r.useRef)(null),[i,a]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{if(!n.current)return;let e=Array.from(n.current.querySelectorAll(".line")),s=[];e.forEach((e,n)=>{e.matches(".highlighted")&&s.push(n),/^\s+$/g.test(e.innerHTML)&&e.setAttribute("data-empty","")}),s.length&&e.forEach((e,n)=>{let t=s.reduce((e,s)=>Math.min(e,Math.abs(s-n)),1/0);e.setAttribute("data-highlight-distance",Math.min(t,4).toString())})},[i]),(0,t.jsx)("div",{ref:n,style:{marginTop:"1.5rem"},className:i?l().collapsed:l().expanded,onClick:e=>{e.target instanceof Element&&e.target.closest(".line")&&a(!i)},children:s})}},3307:function(e,s,n){"use strict";n.d(s,{Z:function(){return l}});var t=n(7505),r=n(1689);let i={logo:function(){return(0,t.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:"0.25em",fontSize:"32px",fontFamily:"PP Supply Mono",textTransform:"uppercase"},children:[(0,t.jsx)("img",{src:"/images/logos/mud-white.svg",style:{height:"calc(var(--nextra-navbar-height) - 35px)"},alt:"MUD logo"}),"MUD"]})},useNextSeoProps(){let{asPath:e}=(0,r.useRouter)();return{titleTemplate:"/"===e?"MUD – a framework for ambitious Ethereum applications":"%s – MUD"}},project:{link:"https://github.com/latticexyz/mud"},docsRepositoryBase:"https://github.com/latticexyz/mud/tree/main/docs",head:(0,t.jsx)(t.Fragment,{children:(0,t.jsx)("meta",{property:"title",content:"MUD documentation"})}),darkMode:!1,nextThemes:{defaultTheme:"dark"},footer:{text:"MIT 2023 \xa9 MUD"},primaryHue:28,sidebar:{defaultMenuCollapseLevel:1}};var l=i},174:function(e,s,n){"use strict";n.r(s);var t=n(7505),r=n(2585),i=n(8288),l=n(3307);n(4693);var a=n(6736);n(8823);var o=n(4738),c=n(8986);let d={MDXContent:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:s}=Object.assign({},(0,a.ah)(),e.components);return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(h,{...e})}):h(e)},pageOpts:{filePath:"pages/services/indexer.mdx",route:"/services/indexer",headings:[{depth:1,value:"Indexer",id:"indexer"},{depth:2,value:"Why an offchain indexer?",id:"why-an-offchain-indexer"},{depth:2,value:"Installation",id:"installation"},{depth:3,value:"Schemaful indexing to SQLite via npx",id:"schemaful-indexing-to-sqlite-via-npx"},{depth:3,value:"Schemaless indexing to PostgreSQL via npx",id:"schemaless-indexing-to-postgresql-via-npx"},{depth:3,value:"Schemaful indexing with PostgreSQL via npx",id:"schemaful-indexing-with-postgresql-via-npx"},{depth:3,value:"Docker",id:"docker"},{depth:4,value:"SQLite",id:"sqlite"},{depth:4,value:"Schemaless indexing with PostgreSQL via Docker",id:"schemaless-indexing-with-postgresql-via-docker"},{depth:4,value:"Schemaful indexing with PostgreSQL via Docker",id:"schemaful-indexing-with-postgresql-via-docker"},{depth:3,value:"Verification",id:"verification"},{depth:2,value:"Using the indexer",id:"using-the-indexer"},{depth:3,value:"Clearing the information",id:"clearing-the-information"},{depth:2,value:"Usage examples",id:"usage-examples"},{depth:3,value:"SQLite to view the tasks from the React template",id:"sqlite-to-view-the-tasks-from-the-react-template"}],pageMap:[{kind:"Meta",data:{introduction:{title:"What is MUD?",theme:{breadcrumb:!1}},quickstart:{title:"Get started",theme:{breadcrumb:!1}},protocol:{title:"Protocol",type:"separator"},store:"Store",world:"World",framework:{title:"Framework",type:"separator"},config:"Config",cli:"CLI","state-query":"State Query",services:"Services","---":{title:"",type:"separator"},guides:"Guides",templates:"Templates",contribute:{title:"Contribute",theme:{breadcrumb:!1}},changelog:"Changelog",retrospectives:"Retrospectives",audits:"Audits",version:{title:"2.0.9",type:"menu",items:{changelog:{title:"Changelog",href:"/changelog"},contribute:{title:"Contribute",href:"/contribute"}}},status:{title:"Status",type:"page",href:"https://status.mud.dev",newWindow:!0},community:{title:"Community",type:"page",href:"https://community.mud.dev",newWindow:!0},twitter:{title:"Twitter",type:"page",href:"https://twitter.com/latticexyz",newWindow:!0},discord:{title:"Discord",type:"page",href:"https://lattice.xyz/discord",newWindow:!0}}},{kind:"Folder",name:"audits",route:"/audits",children:[{kind:"MdxPage",name:"2024-02-11-open-zeppelin",route:"/audits/2024-02-11-open-zeppelin"},{kind:"Meta",data:{"2024-02-11-open-zeppelin":"2024-02-11 OpenZeppelin",pdf:{display:"hidden"},icons:{display:"hidden"}}}]},{kind:"MdxPage",name:"changelog",route:"/changelog"},{kind:"Folder",name:"cli",route:"/cli",children:[{kind:"Meta",data:{tablegen:"mud tablegen",worldgen:"mud worldgen",test:"mud test",deploy:"mud deploy",verify:"mud verify","dev-contracts":"mud dev-contracts","abi-ts":"mud abi-ts",faucet:"mud faucet","set-version":"mud set-version"}},{kind:"MdxPage",name:"abi-ts",route:"/cli/abi-ts"},{kind:"MdxPage",name:"deploy",route:"/cli/deploy"},{kind:"MdxPage",name:"dev-contracts",route:"/cli/dev-contracts"},{kind:"MdxPage",name:"faucet",route:"/cli/faucet"},{kind:"MdxPage",name:"set-version",route:"/cli/set-version"},{kind:"MdxPage",name:"tablegen",route:"/cli/tablegen"},{kind:"MdxPage",name:"test",route:"/cli/test"},{kind:"MdxPage",name:"verify",route:"/cli/verify"},{kind:"MdxPage",name:"worldgen",route:"/cli/worldgen"}]},{kind:"MdxPage",name:"config",route:"/config"},{kind:"MdxPage",name:"contribute",route:"/contribute"},{kind:"Folder",name:"guides",route:"/guides",children:[{kind:"Meta",data:{"replicating-onchain-state":"Replicating onchain state","hello-world":"Hello World","extending-a-world":"Extending a World","adding-delegation":"Adding Delegation",emojimon:"Emojimon","best-practices":"Best Practices"}},{kind:"MdxPage",name:"adding-delegation",route:"/guides/adding-delegation"},{kind:"Folder",name:"best-practices",route:"/guides/best-practices",children:[{kind:"Meta",data:{"system-best-practices":"System Best Practices"}},{kind:"MdxPage",name:"system-best-practices",route:"/guides/best-practices/system-best-practices"}]},{kind:"Folder",name:"emojimon",route:"/guides/emojimon",children:[{kind:"MdxPage",name:"1-preface-the-ecs-model",route:"/guides/emojimon/1-preface-the-ecs-model"},{kind:"MdxPage",name:"2-getting-started",route:"/guides/emojimon/2-getting-started"},{kind:"MdxPage",name:"3-players-and-movement",route:"/guides/emojimon/3-players-and-movement"},{kind:"MdxPage",name:"4-map-and-terrain",route:"/guides/emojimon/4-map-and-terrain"},{kind:"MdxPage",name:"5-a-wild-emojimon-appears",route:"/guides/emojimon/5-a-wild-emojimon-appears"},{kind:"MdxPage",name:"6-advanced",route:"/guides/emojimon/6-advanced"},{kind:"Meta",data:{"1-preface-the-ecs-model":"Preface: the ECS model","2-getting-started":"Getting started","3-players-and-movement":"Players and movement","4-map-and-terrain":"Map and terrain","5-a-wild-emojimon-appears":"A wild Emojimon appears","6-advanced":"Advanced features"}}]},{kind:"MdxPage",name:"emojimon",route:"/guides/emojimon"},{kind:"Folder",name:"extending-a-world",route:"/guides/extending-a-world",children:[{kind:"Meta",data:{index:"Extending a World Permissionlessly"}},{kind:"MdxPage",name:"index",route:"/guides/extending-a-world"}]},{kind:"Folder",name:"hello-world",route:"/guides/hello-world",children:[{kind:"Meta",data:{"add-table":"Add a table","filter-sync":"Filter data synchronization","add-system":"Add a system",deploy:{title:"Deploy to a blockchain",href:"/cli/deploy"}}},{kind:"MdxPage",name:"add-system",route:"/guides/hello-world/add-system"},{kind:"MdxPage",name:"add-table",route:"/guides/hello-world/add-table"},{kind:"MdxPage",name:"filter-sync",route:"/guides/hello-world/filter-sync"}]},{kind:"MdxPage",name:"hello-world",route:"/guides/hello-world"},{kind:"MdxPage",name:"replicating-onchain-state",route:"/guides/replicating-onchain-state"}]},{kind:"MdxPage",name:"introduction",route:"/introduction"},{kind:"MdxPage",name:"quickstart",route:"/quickstart"},{kind:"Folder",name:"retrospectives",route:"/retrospectives",children:[{kind:"MdxPage",name:"2023-09-12-register-system-vulnerability",route:"/retrospectives/2023-09-12-register-system-vulnerability"},{kind:"MdxPage",name:"2024-04-17-storeread-getdynamicfieldlength-bug",route:"/retrospectives/2024-04-17-storeread-getdynamicfieldlength-bug"},{kind:"Meta",data:{"2024-04-17-storeread-getdynamicfieldlength-bug":"2024-04-17 StoreRead.getDynamicFieldLength bug","2023-09-12-register-system-vulnerability":"2023-09-12 registerSystem vulnerability"}}]},{kind:"Folder",name:"services",route:"/services",children:[{kind:"Meta",data:{indexer:"Indexer",faucet:"Faucet"}},{kind:"MdxPage",name:"faucet",route:"/services/faucet"},{kind:"MdxPage",name:"indexer",route:"/services/indexer"}]},{kind:"Folder",name:"state-query",route:"/state-query",children:[{kind:"Meta",data:{typescript:"TypeScript"}},{kind:"Folder",name:"typescript",route:"/state-query/typescript",children:[{kind:"Meta",data:{recs:"RECS",zustand:"Zustand"}},{kind:"MdxPage",name:"recs",route:"/state-query/typescript/recs"},{kind:"MdxPage",name:"zustand",route:"/state-query/typescript/zustand"}]}]},{kind:"Folder",name:"store",route:"/store",children:[{kind:"Meta",data:{introduction:"Introduction","data-model":"Data model",tables:"Tables","table-libraries":"Table libraries",encoding:"Encoding","store-hooks":"Store hooks",reference:"Reference"}},{kind:"MdxPage",name:"data-model",route:"/store/data-model"},{kind:"MdxPage",name:"encoding",route:"/store/encoding"},{kind:"MdxPage",name:"introduction",route:"/store/introduction"},{kind:"Folder",name:"reference",route:"/store/reference",children:[{kind:"Meta",data:{"store-core":"StoreCore (internal)",store:"IStore (external)","store-hook":"StoreHook",misc:"Miscellaneous"}},{kind:"MdxPage",name:"misc",route:"/store/reference/misc"},{kind:"MdxPage",name:"store-core",route:"/store/reference/store-core"},{kind:"MdxPage",name:"store-hook",route:"/store/reference/store-hook"},{kind:"MdxPage",name:"store",route:"/store/reference/store"}]},{kind:"MdxPage",name:"store-hooks",route:"/store/store-hooks"},{kind:"MdxPage",name:"table-libraries",route:"/store/table-libraries"},{kind:"MdxPage",name:"tables",route:"/store/tables"}]},{kind:"Folder",name:"templates",route:"/templates",children:[{kind:"Meta",data:{typescript:"TypeScript",godot:"Godot",pwa:"Progressive Web App (for mobile)",swift:"Swift",svelte:"Svelte",unity:"Unity"}},{kind:"MdxPage",name:"godot",route:"/templates/godot"},{kind:"MdxPage",name:"pwa",route:"/templates/pwa"},{kind:"MdxPage",name:"svelte",route:"/templates/svelte"},{kind:"MdxPage",name:"swift",route:"/templates/swift"},{kind:"Folder",name:"typescript",route:"/templates/typescript",children:[{kind:"Meta",data:{contracts:"Contracts",vanilla:"Vanilla","react-ecs":"React-ECS",threejs:"Three.js",vue:"Vue"}},{kind:"MdxPage",name:"contracts",route:"/templates/typescript/contracts"},{kind:"MdxPage",name:"react-ecs",route:"/templates/typescript/react-ecs"},{kind:"MdxPage",name:"threejs",route:"/templates/typescript/threejs"},{kind:"MdxPage",name:"vanilla",route:"/templates/typescript/vanilla"},{kind:"MdxPage",name:"vue",route:"/templates/typescript/vue"}]},{kind:"MdxPage",name:"unity",route:"/templates/unity"}]},{kind:"Folder",name:"world",route:"/world",children:[{kind:"Meta",data:{introduction:"Introduction","resource-ids":"Resource Identifiers","namespaces-access-control":"Namespaces & Access Control",tables:"Tables",systems:"Systems","system-hooks":"System Hooks","function-selectors":"Function Selectors",balance:"Balance","account-delegation":"Account Delegation","batch-calls":"Batch Calls",upgrades:"Upgrading",modules:"Modules",reference:"Reference"}},{kind:"MdxPage",name:"account-delegation",route:"/world/account-delegation"},{kind:"MdxPage",name:"balance",route:"/world/balance"},{kind:"MdxPage",name:"batch-calls",route:"/world/batch-calls"},{kind:"MdxPage",name:"function-selectors",route:"/world/function-selectors"},{kind:"MdxPage",name:"introduction",route:"/world/introduction"},{kind:"Folder",name:"modules",route:"/world/modules",children:[{kind:"Meta",data:{keyswithvalue:"Keys with Value"}},{kind:"MdxPage",name:"keyswithvalue",route:"/world/modules/keyswithvalue"}]},{kind:"MdxPage",name:"modules",route:"/world/modules"},{kind:"MdxPage",name:"namespaces-access-control",route:"/world/namespaces-access-control"},{kind:"Folder",name:"reference",route:"/world/reference",children:[{kind:"Meta",data:{"delegation-external":"Delegation (interface)",module:"Modules","module-external":"Modules (interface)",system:"Systems","system-external":"Systems (interface)",world:"World","world-external":"World (interfaces)","world-context":"World context","world-context-external":"World context (interface)","resource-ids":"Resource IDs",misc:"Miscellaneous",internal:"Internals"}},{kind:"MdxPage",name:"delegation-external",route:"/world/reference/delegation-external"},{kind:"Folder",name:"internal",route:"/world/reference/internal",children:[{kind:"Meta",data:{"access-control":"Access Control",create:"Create2",delegation:"Delegation",erc165:"ERC165","erc165-external":"ERC165 (interface)","init-module":"Init Module","init-module-implementation":"Init Module Implementation",systemcall:"SystemCall"}},{kind:"MdxPage",name:"access-control",route:"/world/reference/internal/access-control"},{kind:"MdxPage",name:"create",route:"/world/reference/internal/create"},{kind:"MdxPage",name:"delegation",route:"/world/reference/internal/delegation"},{kind:"MdxPage",name:"erc165-external",route:"/world/reference/internal/erc165-external"},{kind:"MdxPage",name:"erc165",route:"/world/reference/internal/erc165"},{kind:"MdxPage",name:"init-module-implementation",route:"/world/reference/internal/init-module-implementation"},{kind:"MdxPage",name:"init-module",route:"/world/reference/internal/init-module"},{kind:"MdxPage",name:"systemcall",route:"/world/reference/internal/systemcall"}]},{kind:"MdxPage",name:"misc",route:"/world/reference/misc"},{kind:"MdxPage",name:"module-external",route:"/world/reference/module-external"},{kind:"MdxPage",name:"module",route:"/world/reference/module"},{kind:"MdxPage",name:"resource-ids",route:"/world/reference/resource-ids"},{kind:"MdxPage",name:"system-external",route:"/world/reference/system-external"},{kind:"MdxPage",name:"system",route:"/world/reference/system"},{kind:"MdxPage",name:"world-context-external",route:"/world/reference/world-context-external"},{kind:"MdxPage",name:"world-context",route:"/world/reference/world-context"},{kind:"MdxPage",name:"world-external",route:"/world/reference/world-external"},{kind:"MdxPage",name:"world",route:"/world/reference/world"}]},{kind:"MdxPage",name:"resource-ids",route:"/world/resource-ids"},{kind:"MdxPage",name:"system-hooks",route:"/world/system-hooks"},{kind:"MdxPage",name:"systems",route:"/world/systems"},{kind:"MdxPage",name:"tables",route:"/world/tables"},{kind:"MdxPage",name:"upgrades",route:"/world/upgrades"}]}],flexsearch:{codeblocks:!0},title:"Indexer"},pageNextRoute:"/services/indexer",nextraLayout:i.ZP,themeConfig:l.Z};function h(e){let s=Object.assign({h1:"h1",p:"p",h2:"h2",table:"table",thead:"thead",tr:"tr",th:"th",code:"code",tbody:"tbody",td:"td",a:"a",h3:"h3",ol:"ol",li:"li",pre:"pre",span:"span",strong:"strong",ul:"ul",h4:"h4",details:"details",summary:"summary"},(0,a.ah)(),e.components);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{children:"Indexer"}),"\n",(0,t.jsx)(s.p,{children:"The MUD Indexer is an offchain indexer for onchain applications built with MUD."}),"\n",(0,t.jsx)(s.h2,{id:"why-an-offchain-indexer",children:"Why an offchain indexer?"}),"\n",(0,t.jsx)(s.p,{children:"Reads with onchain apps can be tricky.\nWhat does it mean to be able to query the Ethereum network?\nTechnically, given a node with a fully synced state, we can explore just about everything using the EVM, but the “exploring” would be looking at raw storage slots for accounts corresponding to smart contracts.\nA way around this exists by providing view functions on smart contracts: these effectively are just wrappers around raw storage and expose a more friendly API.\nInstead of having to figure out where the balances for an account are stored in the storage tree, we now can call a function that does the lookup via Solidity via an RPC endpoint."}),"\n",(0,t.jsx)(s.p,{children:"The issue with view functions is that for any sophisticated application the calls needed to get the “full picture” of the state from the chain are very complex.\nServicing so many view function calls also creates the need to run a set of dedicated nodes instead of relying on a third-party provider's free tier."}),"\n",(0,t.jsx)(s.p,{children:"The MUD indexer solves this problem by listening to the MUD store events to automatically replicate the entire onchain state in a relational database.\nHaving such a database allows clients to quickly and efficiently query the onchain data."}),"\n",(0,t.jsx)(s.h2,{id:"installation",children:"Installation"}),"\n",(0,t.jsx)(s.p,{children:"These environment variables need to be provided to the indexer to work:"}),"\n",(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Type"}),(0,t.jsx)(s.th,{children:"Variable"}),(0,t.jsx)(s.th,{children:"Meaning"}),(0,t.jsxs)(s.th,{children:["Sample value (using ",(0,t.jsx)(s.code,{children:"anvil"})," running on the host)"]})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Needed"}),(0,t.jsx)(s.td,{children:"RPC_HTTP_URL"}),(0,t.jsx)(s.td,{children:"The URL to access the blockchain using HTTP"}),(0,t.jsxs)(s.td,{children:[(0,t.jsx)(s.a,{href:"http://host.docker.internal:8545",children:"http://host.docker.internal:8545"})," (when running in Docker)"]})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Optional"}),(0,t.jsx)(s.td,{children:"RPC_WS_URL"}),(0,t.jsx)(s.td,{children:"The URL to access the blockchain using WebSocket"}),(0,t.jsx)(s.td,{})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Optional"}),(0,t.jsx)(s.td,{children:"START_BLOCK"}),(0,t.jsxs)(s.td,{children:["The block to start indexing from. The block in which the ",(0,t.jsx)(s.code,{children:"World"})," contract was deployed is a good choice."]}),(0,t.jsx)(s.td,{children:"1"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Optional"}),(0,t.jsx)(s.td,{children:"DEBUG=mud:*"}),(0,t.jsx)(s.td,{children:"Turn on debugging"}),(0,t.jsx)(s.td,{})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Optional"}),(0,t.jsx)(s.td,{children:"STORE_ADDRESS"}),(0,t.jsxs)(s.td,{children:["Only index tables from this ",(0,t.jsx)(s.code,{children:"World"})]}),(0,t.jsx)(s.td,{})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Optional, only for SQLite"}),(0,t.jsx)(s.td,{children:"SQLITE_FILENAME"}),(0,t.jsx)(s.td,{children:"Name of database"}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"indexer.db"})})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Required for PostgreSQL"}),(0,t.jsx)(s.td,{children:"DATABASE_URL"}),(0,t.jsxs)(s.td,{children:["URL for the database, of the form ",(0,t.jsx)(s.code,{children:"postgres://<host>/<database>"})]}),(0,t.jsx)(s.td,{})]})]})]}),"\n",(0,t.jsx)(s.h3,{id:"schemaful-indexing-to-sqlite-via-npx",children:"Schemaful indexing to SQLite via npx"}),"\n",(0,t.jsx)(s.p,{children:"To run the indexer directly on your computer using SQLite:"}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Start a ",(0,t.jsx)(s.code,{children:"World"})," to index.\nAn easy way to do this is to ",(0,t.jsx)(s.a,{href:"/templates/typescript/getting-started",children:"use a TypeScript template"})," in a separate command line window."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Set ",(0,t.jsx)(s.code,{children:"RPC_HTTP_URL"}),"."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"bash","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" RPC_HTTP_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"http://127.0.0.1:8545"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Run the indexer.\nIf necessary, install it first."}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"bash","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"npx"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-y"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"@latticexyz/store-indexer"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"sqlite-indexer"})]})})}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(s.p,{children:[(0,t.jsx)(s.strong,{children:"Note:"})," The ",(0,t.jsx)(s.code,{children:"indexer.db"})," is persistent if you stop and restart the indexer.\nIf that is not the desired behavior (for example, because you restarted the blockchain itself), delete it before starting the indexer."]}),"\n",(0,t.jsx)(s.h3,{id:"schemaless-indexing-to-postgresql-via-npx",children:"Schemaless indexing to PostgreSQL via npx"}),"\n",(0,t.jsxs)(s.p,{children:["The schemaless indexer stores MUD table records into a single monolithic table.\nThis allows it to index the data of all tables of all MUD Worlds on a chain efficiently, but querying for data is limited to filters on ",(0,t.jsx)(s.code,{children:"address"}),", ",(0,t.jsx)(s.code,{children:"tableId"}),", and the record's key.\nSince the record's ",(0,t.jsx)(s.code,{children:"data"})," is stored as encoded bytes blob, it's harder to query based on it in SQL.\nThe main purpose of this variant of the indexer is to efficiently hydrate a MUD client, which decodes the data."]}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Start a ",(0,t.jsx)(s.code,{children:"World"})," to index.\nAn easy way to do this is to ",(0,t.jsx)(s.a,{href:"/templates/typescript/getting-started",children:"use a TypeScript template"})," in a separate command line window."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Set the environment variables."}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"bash","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" RPC_HTTP_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"http://127.0.0.1:8545"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" DATABASE_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres://127.0.0.1/postgres"})]})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Run the indexer.\nInstall it first if necessary."}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"bash","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"npx"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-y"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"@latticexyz/store-indexer"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres-indexer"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Open a separate command line.\nIn it, specify the database and run the indexer frontend, which is responsible for serving the data to the client."}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"bash","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" DATABASE_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres://127.0.0.1/postgres"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"npx"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-y"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"@latticexyz/store-indexer"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres-frontend"})]})]})}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"schemaful-indexing-with-postgresql-via-npx",children:"Schemaful indexing with PostgreSQL via npx"}),"\n",(0,t.jsx)(s.p,{children:"The schemaful indexer dynamically creates a PostgreSQL table every time it encounters a new MUD table.\nIt then decodes the MUD events and stores it in the PostgreSQL table with a matching schema.\nThis approach doesn't scale well to all tables of a chain, but it is a convenient way to index the tables of a particular MUD World and have access to powerful SQL queries on its data."}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Start a ",(0,t.jsx)(s.code,{children:"World"})," to index.\nAn easy way to do this is to ",(0,t.jsx)(s.a,{href:"/templates/typescript/getting-started",children:"use a TypeScript template"})," in a separate command line window."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Set the environment variables and start the indexer, installing it if necessary."}),"\n",(0,t.jsx)(s.pre,{"data-language":"bash","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"bash","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" RPC_HTTP_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"http://127.0.0.1:8545"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" DATABASE_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres://127.0.0.1/postgres"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"npx"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-y"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"@latticexyz/store-indexer"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"postgres-decoded-indexer"})]})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["To verify the installation, run ",(0,t.jsx)(s.code,{children:"psql"})," and then:"]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"List the schemas."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"\\dn"})})})}),"\n",(0,t.jsx)(s.p,{children:"Result:"}),"\n",(0,t.jsx)(s.pre,{"data-language":"text","data-theme":"default",children:(0,t.jsxs)(s.code,{"data-language":"text","data-theme":"default",children:[(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"                  List of schemas"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"                  Name                    | Owner"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"--------------------------------------------+-------"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"mud                                        | qbzzt"})})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Connect to the schema for your world."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SET"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" search_path "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"TO"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:";"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Get the list of tables."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"\\dt"})})})}),"\n",(0,t.jsx)(s.p,{children:"Result (When using the React template):"}),"\n",(0,t.jsx)(s.pre,{"data-language":"text","data-theme":"default",children:(0,t.jsxs)(s.code,{"data-language":"text","data-theme":"default",children:[(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"                                 List of relations"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"                  Schema                   |           Name            | Type  | Owner"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"--------------------------------------------+---------------------------+-------+-------"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | store__resource_ids       | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | store__store_hooks        | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | store__tables             | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | tasks                     | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__balances           | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__function_selector  | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__function_signatur  | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__init_module_addres | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__installed_modules  | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__namespace_delegat  | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__namespace_owner    | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__resource_access    | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__system_hooks       | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__system_registry    | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__systems            | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1 | world__user_delegation_co | table | qbzzt"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"(16 rows)"})})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Read the actual data."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SELECT"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"*"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"FROM"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" tasks;"})]})})}),"\n",(0,t.jsx)(s.p,{children:"Result:"}),"\n",(0,t.jsx)(s.pre,{"data-language":"text","data-theme":"default",children:(0,t.jsxs)(s.code,{"data-language":"text","data-theme":"default",children:[(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"                                id                                 | created_at | completed_at |    description     |                            __key_bytes                             | __last_updated_block_number"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"-------------------------------------------------------------------+------------+--------------+--------------------+--------------------------------------------------------------------+-----------------------------"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"\\x3100000000000000000000000000000000000000000000000000000000000000 | 1712714176 |            0 | Walk the dog       | \\x3100000000000000000000000000000000000000000000000000000000000000 |                          10"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"\\x5e9c11602057fbf149cca23095b1863f7ffa8d0d0bd9434005a344ad612488a7 | 1712714178 |            0 | Take out the trash | \\x5e9c11602057fbf149cca23095b1863f7ffa8d0d0bd9434005a344ad612488a7 |                          10"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"\\x0c9151148be227a42be8d3e3e7e61da28a532f2340b0ad9ca8bc747703ec2417 | 1712714178 |   1712714178 | Do the dishes      | \\x0c9151148be227a42be8d3e3e7e61da28a532f2340b0ad9ca8bc747703ec2417 |                          10"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"(3 rows)"})})]})}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"docker",children:"Docker"}),"\n",(0,t.jsxs)(s.p,{children:["The indexer Docker image is available ",(0,t.jsx)(s.a,{href:"https://github.com/latticexyz/mud/pkgs/container/store-indexer",children:"on github"}),"."]}),"\n",(0,t.jsxs)(s.p,{children:["There are several ways to provide the environment variables to ",(0,t.jsx)(s.code,{children:"docker run"}),":"]}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["On the command line you can specify ",(0,t.jsx)(s.code,{children:"-e <variable>=<value>"}),".\nYou specify this after the ",(0,t.jsx)(s.code,{children:"docker run"}),", but before the name of the image."]}),"\n",(0,t.jsxs)(s.li,{children:["You can also write all the environment variables in a file and specify it using ",(0,t.jsx)(s.code,{children:"--env-file"}),".\nYou specify this after the ",(0,t.jsx)(s.code,{children:"docker run"}),", but before the name of the image."]}),"\n",(0,t.jsxs)(s.li,{children:["Both ",(0,t.jsx)(s.a,{href:"https://docs.docker.com/compose/",children:"Docker Compose"})," and ",(0,t.jsx)(s.a,{href:"https://kubernetes.io/",children:"Kubernetes"})," have their own mechanisms for starting docker containers with environment variables."]}),"\n"]}),"\n",(0,t.jsxs)(s.p,{children:["The easiest way to test the indexer is to ",(0,t.jsx)(s.a,{href:"/templates/typescript/getting-started",children:"run the template as a world"})," in a separate command-line window."]}),"\n",(0,t.jsx)(s.h4,{id:"sqlite",children:"SQLite"}),"\n",(0,t.jsxs)(s.p,{children:["The command to start the indexer in SQLite mode is ",(0,t.jsx)(s.code,{children:"pnpm start:sqlite"}),".\nTo index an ",(0,t.jsx)(s.code,{children:"anvil"})," instance running to the host you can use this command."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"run"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--platform"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"linux/amd64"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"RPC_HTTP_URL=http://host.docker.internal:8545"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:":3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ghcr.io/latticexyz/store-indexer:latest"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"pnpm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"start:sqlite"})]})]})}),"\n",(0,t.jsxs)(s.p,{children:["However, this creates a docker container with a state, the SQLite database file.\nIf we start a new container with the same image and parameters, it is going to have to go back to the start of the blockchain, which depending on how long the blockchain has been in use may be a problem.\nWe can solve this with ",(0,t.jsx)(s.a,{href:"https://docs.docker.com/storage/volumes/",children:"volumes"}),":"]}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Create a docker volume for the SQLite database file."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sh","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"volume"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"create"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"sqlite-db-file"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Run the indexer container using the volume."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"run"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--platform"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"linux/amd64"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"RPC_HTTP_URL=http://host.docker.internal:8545"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"SQLITE_FILENAME=/dbase/indexer.db"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-v"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"sqlite-db-file:/dbase"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:":3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ghcr.io/latticexyz/store-indexer:latest"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"   "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"pnpm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"start:sqlite"})]})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"You can stop the docker container and restart it, or start a separate container using the same database."}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"When you are done, you have to delete the docker containers that used it before you can delete the volume.\nYou can use these commands:"}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"rm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"`"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ps"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-a"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--filter"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"volume=sqlite-db-file"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-q"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"`"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"volume"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"rm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"sqlite-db-file"})]})]})}),"\n",(0,t.jsxs)(s.p,{children:[(0,t.jsx)(s.strong,{children:"Note:"})," You should do this every time you restart the blockchain.\nOtherwise your index will include data from multiple blockchains, and make no sense."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h4,{id:"schemaless-indexing-with-postgresql-via-docker",children:"Schemaless indexing with PostgreSQL via Docker"}),"\n",(0,t.jsxs)(s.p,{children:["The command to start the indexer in schemaless PostgreSQL mode is ",(0,t.jsx)(s.code,{children:"pnpm start:postgres"}),".\nThis command starts both the indexer and query frontends."]}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["The docker instance identifies itself to PostgreSQL as ",(0,t.jsx)(s.code,{children:"root"}),".\nTo give this user permissions on the database, enter ",(0,t.jsx)(s.code,{children:"psql"})," and run this command."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"CREATE"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"ROLE"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"root"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" SUPERUSER "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"LOGIN"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:";"})]})})}),"\n",(0,t.jsxs)(s.p,{children:[(0,t.jsx)(s.strong,{children:"Note:"})," This is assuming a database that is isolated from the internet and only used by trusted entities.\nIn a production system you will use at least a password as authentication, and limit the user's authority."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Start the docker container.\nFor example, to index an ",(0,t.jsx)(s.code,{children:"anvil"})," instance running to the host to the database ",(0,t.jsx)(s.code,{children:"postgres"})," on the host, use."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"run"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--platform"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"linux/amd64"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"RPC_HTTP_URL=http://host.docker.internal:8545"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"DATABASE_URL=postgres://host.docker.internal/postgres"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:":3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ghcr.io/latticexyz/store-indexer:latest"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"pnpm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"start:postgres"})]})]})}),"\n",(0,t.jsx)(s.p,{children:"If you want to create additional query frontends (for reliability and load balancing), use these commands:"}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"HOST_PORT"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"3002"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"run"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--platform"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"linux/amd64"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"DATABASE_URL=postgres://host.docker.internal/postgres"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" $HOST_PORT"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:":3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ghcr.io/latticexyz/store-indexer:latest"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"node"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"dist/bin/postgres-frontend.js"})]})]})}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h4,{id:"schemaful-indexing-with-postgresql-via-docker",children:"Schemaful indexing with PostgreSQL via Docker"}),"\n",(0,t.jsxs)(s.p,{children:["The command to start the indexer in schemaful PostgreSQL mode is ",(0,t.jsx)(s.code,{children:"pnpm start:postgres-decoded"}),".\nThis command starts both the indexer and the query frontend."]}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["The docker instance identifies itself to PostgreSQL as ",(0,t.jsx)(s.code,{children:"root"}),".\nTo give this user permissions on the database, enter ",(0,t.jsx)(s.code,{children:"psql"})," and run this command."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"CREATE"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"ROLE"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"root"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" SUPERUSER "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"LOGIN"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:";"})]})})}),"\n",(0,t.jsxs)(s.p,{children:[(0,t.jsx)(s.strong,{children:"Note:"})," This is assuming a database that is isolated from the internet and only used by trusted entities.\nIn a production system you will use at least a password as authentication, and limit the user's authority."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Start the docker container.\nFor example, to index an ",(0,t.jsx)(s.code,{children:"anvil"})," instance running to the host to the database ",(0,t.jsx)(s.code,{children:"postgres"})," on the host, use."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"docker"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"run"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"--platform"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"linux/amd64"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"RPC_HTTP_URL=http://host.docker.internal:8545"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-e"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"DATABASE_URL=postgres://host.docker.internal/postgres"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:":3001"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"ghcr.io/latticexyz/store-indexer:latest"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  \\"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"pnpm"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"start:postgres-decoded"})]})]})}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h3,{id:"verification",children:"Verification"}),"\n",(0,t.jsx)(s.p,{children:"If you use either SQLite or PostgreSQL with the query frontend (using PostgreSQL only as storage), you can run this command to test the indexer."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sh","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"curl"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'http://localhost:3001/trpc/findAll?batch=1&input=%7B%20%220%22%3A%20%7B%22json%22%3A%20%7B%22chainId%22%3A%2031337%2C%20%22address%22%3A%20%220xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1%22%20%7D%20%7D%20%7D'"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"jq"})]})})}),"\n",(0,t.jsxs)(s.p,{children:["The result should be nicely formatted (and long) JSON output with all the data stored in the ",(0,t.jsx)(s.code,{children:"World"}),"."]}),"\n",(0,t.jsxs)(s.details,{children:[(0,t.jsx)(s.summary,{children:"Where does this URL come from?"}),(0,t.jsx)(s.p,{children:"The URL has these parameters:"}),(0,t.jsxs)(s.table,{children:[(0,t.jsx)(s.thead,{children:(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.th,{children:"Parameter"}),(0,t.jsx)(s.th,{children:"Value"}),(0,t.jsx)(s.th,{children:"Explanation"})]})}),(0,t.jsxs)(s.tbody,{children:[(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Server"}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.a,{href:"http://localhost:3001",children:"http://localhost:3001"})}),(0,t.jsx)(s.td,{children:"By default the indexer listens on port 3001"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:"Path"}),(0,t.jsx)(s.td,{children:"trpc/findAll"}),(0,t.jsx)(s.td,{children:"Return all entries (based on the input filter)"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"batch"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"1"})}),(0,t.jsx)(s.td,{children:"A required field"})]}),(0,t.jsxs)(s.tr,{children:[(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"input"})}),(0,t.jsx)(s.td,{children:(0,t.jsx)(s.code,{children:"%7B%20 ... %20%7D"})}),(0,t.jsx)(s.td,{children:"See below"})]})]})]}),(0,t.jsxs)(s.p,{children:["The input is the JSON filter that tells the server what we need.\nIt is ",(0,t.jsx)(s.a,{href:"https://en.wikipedia.org/wiki/Percent-encoding",children:"URL encoded"}),", you can decode it ",(0,t.jsx)(s.a,{href:"https://www.urldecoder.org/",children:"using an online calculator"}),"."]}),(0,t.jsx)(s.pre,{"data-language":"json","data-theme":"default",children:(0,t.jsxs)(s.code,{"data-language":"json","data-theme":"default",children:[(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"{"})}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:'"0"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" {"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"    "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:'"json"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" {"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"      "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:'"chainId"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"31337"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"      "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:'"address"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1"'})]}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"    }"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  }"})}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"}"})})]})}),(0,t.jsxs)(s.p,{children:["Meaning that query 0 is for everything in the ",(0,t.jsx)(s.code,{children:"World"})," at address ",(0,t.jsx)(s.code,{children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1"}),", on the chain with chain ID ",(0,t.jsx)(s.code,{children:"31337"}),"."]})," ",(0,t.jsx)(o.UW,{type:"info",emoji:"ⓘ",children:(0,t.jsx)(s.p,{children:"The JSON here is written in multiple lines for readablility.\nHowever, when you encode the JSON for the URL it is necessary to place the entire string on one line."})})]}),"\n",(0,t.jsx)(s.h2,{id:"using-the-indexer",children:"Using the indexer"}),"\n",(0,t.jsxs)(s.p,{children:["The source code of a MUD client has a call either to ",(0,t.jsx)(s.a,{href:"https://github.com/latticexyz/mud/blob/main/packages/store-sync/src/recs/syncToRecs.ts#L21-L82",children:(0,t.jsx)(s.code,{children:"syncToRecs"})})," or to ",(0,t.jsx)(s.a,{href:"https://github.com/latticexyz/mud/blob/main/packages/store-sync/src/zustand/syncToZustand.ts#L33-L74",children:(0,t.jsx)(s.code,{children:"syncToZustand"})}),", typically in ",(0,t.jsx)(s.a,{href:"https://github.com/latticexyz/mud/blob/main/templates/react/packages/client/src/mud/setupNetwork.ts#L74-L79",children:(0,t.jsx)(s.code,{children:"setupNetwork.ts"})}),".\nThis call initializes the synchronization between the data source (RPC or indexer) and the client's copy."]}),"\n",(0,t.jsxs)(s.p,{children:["To use the indexer, specify an ",(0,t.jsx)(s.code,{children:"indexerUrl"})," parameter with the URL."]}),"\n",(0,t.jsx)(c.C,{children:(0,t.jsx)(s.pre,{"data-language":"ts","data-theme":"default",children:(0,t.jsxs)(s.code,{"data-language":"ts","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"const"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" { "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"components"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"latestBlock$"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"storedBlockLogs$"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"waitForTransaction"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" } "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"await"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"syncToRecs"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"({"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  world"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  config"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" mudConfig"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  address"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"networkConfig"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:".worldAddress "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"as"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"Hex"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  publicClient"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  startBlock"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"BigInt"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"("}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"networkConfig"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:".initialBlockNumber)"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsxs)(s.span,{className:"line highlighted",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  indexerUrl"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:":"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'"http://127.0.0.1:3001"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-punctuation)"},children:","})]}),"\n",(0,t.jsx)(s.span,{className:"line",children:(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"});"})})]})})}),"\n",(0,t.jsxs)(s.p,{children:["If the client does not need all the information stored in the ",(0,t.jsx)(s.code,{children:"World"}),", you can ",(0,t.jsx)(s.a,{href:"/guides/hello-world/filter-sync",children:"filter the synchronization"})," to save on resources."]}),"\n",(0,t.jsx)(s.h3,{id:"clearing-the-information",children:"Clearing the information"}),"\n",(0,t.jsx)(s.p,{children:"If you restart the blockchain, you need to clear all the information stored by the indexer otherwise you'll have an inconsistent state."}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["If you are using SQLite, remove ",(0,t.jsx)(s.code,{children:"indexer.db"}),"."]}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["If you are using schemaless PostgreSQL, you just need to remove the ",(0,t.jsx)(s.code,{children:"mud"})," schema:"]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"DROP"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SCHEMA"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'"mud"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" CASCADE;"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["If you are using schemaful PostgreSQL, you need to also remove the schemas for the ",(0,t.jsx)(s.code,{children:"World"}),"s indexed."]}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Get the list of ",(0,t.jsx)(s.code,{children:"World"}),"s using this command:"]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SELECT DISTINCT"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"address"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"FROM"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" mud.records;"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Delete those schemas.\nFor example, if you use one of the TypeScript templates, run this command:"}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"DROP"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SCHEMA"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1"'}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" CASCADE;"})]})})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Drop the ",(0,t.jsx)(s.code,{children:"mud"})," schema."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sql","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sql","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"DROP"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"SCHEMA"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" mud CASCADE;"})]})})}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"usage-examples",children:"Usage examples"}),"\n",(0,t.jsx)(s.h3,{id:"sqlite-to-view-the-tasks-from-the-react-template",children:"SQLite to view the tasks from the React template"}),"\n",(0,t.jsxs)(s.ol,{children:["\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Start the indexer."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"export"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" RPC_HTTP_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"http://127.0.0.1:8545"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"npx"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-y"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"-p"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"@latticexyz/store-indexer"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"sqlite-indexer"})]})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsx)(s.p,{children:"Get the list of tables.\nTo do that, we read all the data and filter it locally."}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"curl"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'http://localhost:3001/trpc/findAll?batch=1&input=%7B%220%22%3A%7B%22json%22%3A%7B%22chainId%22%3A31337%2C%22address%22%3A%220x4f4ddafbc93cf8d11a253f21ddbcf836139efdec%22%7D%7D%7D'"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:">"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"alldata.json"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"cat"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"alldata.json"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"jq"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'.[0].result.data.json.tables[]'"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:">"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"tables.json"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"cat"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"tables.json"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"jq"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'\'.namespace + "__" + .name + " " + .tableId\''})]})]})}),"\n"]}),"\n",(0,t.jsxs)(s.li,{children:["\n",(0,t.jsxs)(s.p,{children:["Ask the indexer for only the information in a specific table (which requires you to know the ",(0,t.jsx)(s.code,{children:"tableId"})," for it)."]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsxs)(s.code,{"data-language":"sh","data-theme":"default",children:[(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"INDEXER_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"http://localhost:3001/trpc"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"WORLD_ADDRESS"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"0xc14fbdb7808d9e2a37c1a45b635c8c3ff64a1cc1"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"TABLE_ID"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"0x746200000000000000000000000000005461736b730000000000000000000000"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"CHAIN_ID"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-constant)"},children:"31337"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"JSON"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'\'{"0":{"json":{"chainId": \''}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"$CHAIN_ID"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'\', "address": "\''}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"$WORLD_ADDRESS"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:'\'", "filters": [{"tableId": "\''}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"$TABLE_ID"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'\"}]}}}'"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"ENCODED_JSON"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"="}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"`"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"echo"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" \"console.log(encodeURI('$JSON'))\" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"node"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"`"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"curl"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" $INDEXER_URL"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'/findAll?batch=1&input='"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"$ENCODED_JSON "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:">"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"data.json"})]}),"\n",(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"cat"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"data.json"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:"  "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"jq"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'.[0].result.data.json.tables[0].records'"})]})]})}),"\n",(0,t.jsxs)(s.p,{children:["To see that the only table returned is ",(0,t.jsx)(s.code,{children:"Tasks"}),", run this command:"]}),"\n",(0,t.jsx)(s.pre,{"data-language":"sh","data-theme":"default",hasCopyCode:!0,children:(0,t.jsx)(s.code,{"data-language":"sh","data-theme":"default",children:(0,t.jsxs)(s.span,{className:"line",children:[(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"cat"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string)"},children:"data.json"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-keyword)"},children:"|"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-function)"},children:"jq"}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-color-text)"},children:" "}),(0,t.jsx)(s.span,{style:{color:"var(--shiki-token-string-expression)"},children:"'.[0].result.data.json.tables[].name'"})]})})}),"\n"]}),"\n"]})]})}s.default=(0,r.j)(d)},4737:function(e){e.exports={collapsed:"CollapseCode_collapsed__D1CXB",expanded:"CollapseCode_expanded__x1xKU"}}},function(e){e.O(0,[3720,2888,179],function(){return e(e.s=2990)}),_N_E=e.O()}]);