1"use strict";(self.webpackChunkcompose_documentation=self.webpackChunkcompose_documentation||[]).push([["8907"],{29237(e,t,n){n.r(t),n.d(t,{metadata:()=>o,default:()=>m,frontMatter:()=>l,contentTitle:()=>c,toc:()=>d,assets:()=>r});var o=JSON.parse('{"id":"foundations/custom-facets","title":"Custom Facets \u2014 Build Your Own","description":"Build your own facets that work seamlessly with existing Compose Functionality.","source":"@site/docs/foundations/custom-facets.mdx","sourceDirName":"foundations","slug":"/foundations/custom-facets","permalink":"/docs/foundations/custom-facets","draft":false,"unlisted":false,"editUrl":"https://github.com/Perfect-Abstractions/Compose/tree/main/website/docs/foundations/custom-facets.mdx","tags":[],"version":"current","sidebarPosition":7,"frontMatter":{"sidebar_position":7,"title":"Custom Facets \u2014 Build Your Own","sidebar_label":"Custom Facets","description":"Build your own facets that work seamlessly with existing Compose Functionality."},"sidebar":"mainSidebar","previous":{"title":"Facets & Modules","permalink":"/docs/foundations/facets-and-modules"},"next":{"title":"Overview","permalink":"/docs/foundations/"}}'),s=n(62540),a=n(43023),i=n(92550);let l={sidebar_position:7,title:"Custom Facets \u2014 Build Your Own",sidebar_label:"Custom Facets",description:"Build your own facets that work seamlessly with existing Compose Functionality."},c="Custom Facets",r={},d=[];function u(e){let t={br:"br",code:"code",h1:"h1",header:"header",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"custom-facets",children:"Custom Facets"})}),"\n",(0,s.jsxs)(t.p,{children:["Many projects need custom functionality beyond the standard facets.",(0,s.jsx)(t.br,{}),"\n","Compose is designed for this \u2014 you can build and integrate your own facets that work seamlessly alongside existing Compose facets."]}),"\n",(0,s.jsx)(t.p,{children:"Compose provides Solidity modules that expose the same storage layouts and internal logic used by its on-chain facets. This lets your custom facets share data and interact directly with Compose's reusable facets."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Example: Adding Game Logic to ERC-721"})}),"\n",(0,s.jsxs)(t.p,{children:["Suppose you're building an on-chain game and want to include the ",(0,s.jsx)(t.code,{children:"ERC721Facet"})," in your diamond.\nYou can add your own ",(0,s.jsx)(t.code,{children:"GameNFTFacet"})," that extends functionality while still sharing the same ERC-721 storage through ",(0,s.jsx)(t.code,{children:"ERC721Mod"}),":"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-Solidity",children:'/**\n * Your custom facet integrates with Compose using Modules\n */\nimport "compose/ERC721Mod" as ERC721Mod;\n\ncontract GameNFTFacet {\n function mintWithGameLogic(address player, uint256 tokenId) external {\n /**\n * Your custom game logic\n */\n require(playerHasEnoughPoints(player), "Not enough points");\n \n /**\n * Use ERC721Mod to mint - this modifies the SAME storage\n * that ERC721Facet uses for balanceOf(), ownerOf(), etc.\n */\n ERC721Mod.mint(player, tokenId);\n \n /**\n * Now the player owns this NFT and can use standard\n * ERC721Facet.transferFrom() to transfer it!\n */\n updatePlayerStats(player);\n }\n}\n'})}),"\n",(0,s.jsx)(i.A,{type:"tip",title:"Key Insight",children:(0,s.jsxs)(t.p,{children:["Your custom ",(0,s.jsx)(t.code,{children:"GameNFTFacet"})," and the standard ",(0,s.jsx)(t.code,{children:"ERC721Facet"})," both operate on the ",(0,s.jsx)(t.strong,{children:"same storage"})," within your diamond. This shared-storage architecture is what makes composition possible."]})}),"\n",(0,s.jsx)(i.A,{type:"warning",title:"Early State Development",children:(0,s.jsxs)(t.p,{children:["Compose is still in early development and currently available only to contributors.\nIt is not ",(0,s.jsx)(t.strong,{children:"production-ready"})," \u2014 use it in test or development environments only."]})})]})}function m(e={}){let{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},92550(e,t,n){n.d(t,{A:()=>l});var o=n(62540);n(63696);var s=n(11750),a=n(21737);let i={callout:"callout_aeEX",calloutHeader:"calloutHeader_fXny",calloutIcon:"calloutIcon_vX9X",calloutTitle:"calloutTitle_kaV8",calloutContent:"calloutContent_Hl52","callout--info":"callout--info_TgTd","callout--warning":"callout--warning_ioY5","callout--danger":"callout--danger_OAha","callout--success":"callout--success_rrx_","callout--tip":"callout--tip_iqbU","callout--note":"callout--note_gJ54"};function l({type:e="info",title:t,children:n,icon:c=!0}){let r={info:"lightbulb",warning:"warning",danger:"no-entry",success:"checkmark",tip:"lightbulb",note:"memo"};return(0,o.jsxs)("div",{className:(0,s.A)(i.callout,i[`callout--${e}`]),children:[(0,o.jsxs)("div",{className:i.calloutHeader,children:[c&&(0,o.jsx)("span",{className:i.calloutIcon,children:(0,o.jsx)(a.A,{name:r[e]||r.info,size:24})}),t&&(0,o.jsx)("span",{className:i.calloutTitle,children:t})]}),(0,o.jsx)("div",{className:i.calloutContent,children:n})]})}},43023(e,t,n){n.d(t,{R:()=>i,x:()=>l});var o=n(63696);let s={},a=o.createContext(s);function i(e){let t=o.useContext(a);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.