diff --git a/pr-preview/pr-192/404.html b/pr-preview/pr-192/404.html deleted file mode 100644 index c7635f64a..000000000 --- a/pr-preview/pr-192/404.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Page Not Found | Rollkit - - - - - - - - - -
-
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/assets/css/styles.23787291.css b/pr-preview/pr-192/assets/css/styles.23787291.css deleted file mode 100644 index 4ea4501b5..000000000 --- a/pr-preview/pr-192/assets/css/styles.23787291.css +++ /dev/null @@ -1 +0,0 @@ -.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-font-family-base:"RuberoidBold";--ifm-color-primary:#000;--ifm-color-primary-dark:#096fb7;--ifm-color-primary-darker:#0a79c8;--ifm-color-primary-darkest:#0b83d9;--ifm-color-primary-light:#0c8dea;--ifm-color-primary-lighter:#1496f2;--ifm-color-primary-lightest:#fff;--ifm-code-font-size:95%;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.list_eTzJ article:last-child,.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal);max-height:1000px;overflow-y:auto}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration);color:var(--ifm-color-primary-dark)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area.breadcrumbs__link[href]:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.sidebar_re4s,.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.cardContainer_fWXF :last-child,.collapsibleContent_i85q>:last-child,.footer__items,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_f1Hy{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.navbar-sidebar,.navbar-sidebar__backdrop{opacity:0;top:0;transition-timing-function:ease-in-out;bottom:0;left:0;visibility:hidden}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.docsWrapper_BCFX,.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);position:fixed;transform:translate3d(-100%,0,0);transition-duration:.25s;transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;position:fixed;right:0;transition-duration:.1s;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_mo7H:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}@font-face{font-family:RuberoidRegular;src:url(/pr-preview/pr-192/assets/fonts/Ruberoid-Regular-3035d61dd818bff87d11c58a5560b676.otf) format("opentype")}@font-face{font-family:RuberoidBold;src:url(/pr-preview/pr-192/assets/fonts/Ruberoid-Bold-90219d629af095f662e5ec8c2d7dc0d2.otf) format("opentype")}@font-face{font-family:Inter;src:url(/pr-preview/pr-192/assets/fonts/Inter-Regular-2391725004ae05a27e8ed0461a21c71c.ttf) format("truetype")}[data-theme=dark]{--ifm-color-primary:#fff;--ifm-color-primary-dark:#68bbf7;--ifm-color-primary-darker:#79c3f8;--ifm-color-primary-darkest:#89caf8;--ifm-color-primary-light:#9ad2f9;--ifm-color-primary-lighter:#abd9fa;--ifm-color-primary-lightest:#000}[data-theme=dark] .front-page-link{background-color:#000;border:1px solid #ffffff1a;box-shadow:0 4px 12px #000;color:#fff}[data-theme=dark] .front-page-link:hover{border:1px solid #ffffff4d;box-shadow:0 4px 12px #00000080;color:#fff;text-decoration:none}li,p{font-family:Inter}.front-page-link{background-color:#fff;border:1px solid #0000001a;border-radius:7px;box-shadow:0 4px 12px #fff;color:#000;display:flex;flex-direction:column;font-family:RuberoidRegular;font-weight:600;height:115px;justify-content:center;margin:0 8px;padding:0 23px;text-align:left;text-decoration:none;transition:.35s;width:300px}.front-page-link:hover{border:1px solid #0000004d;box-shadow:0 4px 12px #ffffff80;color:#000;text-decoration:none}.button-heading{font-family:RuberoidBold;font-size:22px;line-height:24px;margin:0 0 8px}.youtube-wrapper{overflow:hidden;padding-top:56.25%;position:relative;width:100%}.youtube-video{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#docusaurus-base-url-issue-banner-container,.collapseSidebarButton_PEFL,.docSidebarContainer_b6E3,.sidebarLogo_isFc,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{flex:1 0 auto}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_re4s{overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_pO2u{font-size:var(--ifm-h3-font-size);font-weight:var(--ifm-font-weight-bold)}.container_mt6G,.sidebarItemList_Yudw{font-size:.9rem}.sidebarItem__DBe{margin-top:.7rem}.sidebarItemLink_mo7H{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_I1ZP{color:var(--ifm-color-primary)!important}.cardContainer_fWXF{--ifm-link-color:var(--ifm-color-emphasis-800);--ifm-link-hover-color:var(--ifm-color-emphasis-700);--ifm-link-hover-decoration:none;border:1px solid var(--ifm-color-emphasis-200);box-shadow:0 1.5px 3px 0 #00000026;transition:all var(--ifm-transition-fast) ease;transition-property:border,box-shadow}.cardContainer_fWXF:hover{border-color:var(--ifm-color-primary);box-shadow:0 3px 6px 0 #0003}.cardTitle_rnsV{font-size:1.2rem}.cardDescription_PWke{font-size:.8rem}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.features_t9lD{align-items:center;display:flex;padding:2rem 0;width:100%}.featureSvg_GfXr{height:200px;width:200px}.heroBanner_qdFl{overflow:hidden;padding:4rem 0;position:relative;text-align:center}.buttons_AeoN{align-items:center;display:flex;flex-wrap:wrap;justify-content:center;margin-top:30px}.authorCol_Hf19{flex-grow:1!important;max-width:inherit!important}.imageOnlyAuthorRow_pa_O{display:flex;flex-flow:row wrap}.imageOnlyAuthorCol_G86a{margin-left:.3rem;margin-right:.3rem}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity .2s ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_Nnez{display:inline-block;margin:.5rem .5rem 0 1rem}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:.15s;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.blogPostFooterDetailsFull_mRVl{flex-direction:column}.tableOfContents_bqdL{overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.breadcrumbHomeIcon_OVgt{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.title_kItE{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-leading)*1.25)}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg);position:sticky}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;max-height:100vh;padding-top:var(--ifm-navbar-height);position:sticky;top:0;transition:opacity 50ms;width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{height:0;opacity:0;overflow:hidden;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;max-height:100vh;top:0;transition:background-color var(--ifm-transition-fast) ease}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn,.generatedIndexPage_vN6x{max-width:75%!important}.list_eTzJ article:nth-last-child(-n+2){margin-bottom:0!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media only screen and (max-width:1000px){.front-page-link{margin-bottom:10px;width:100%}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.sidebar_re4s,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media screen and (max-width:996px){.heroBanner_qdFl{padding:2rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_f1Hy{font-size:2rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/pr-preview/pr-192/assets/fonts/Inter-Regular-2391725004ae05a27e8ed0461a21c71c.ttf b/pr-preview/pr-192/assets/fonts/Inter-Regular-2391725004ae05a27e8ed0461a21c71c.ttf deleted file mode 100644 index cc73944ac..000000000 Binary files a/pr-preview/pr-192/assets/fonts/Inter-Regular-2391725004ae05a27e8ed0461a21c71c.ttf and /dev/null differ diff --git a/pr-preview/pr-192/assets/fonts/Ruberoid-Bold-90219d629af095f662e5ec8c2d7dc0d2.otf b/pr-preview/pr-192/assets/fonts/Ruberoid-Bold-90219d629af095f662e5ec8c2d7dc0d2.otf deleted file mode 100644 index d9fae2ea6..000000000 Binary files a/pr-preview/pr-192/assets/fonts/Ruberoid-Bold-90219d629af095f662e5ec8c2d7dc0d2.otf and /dev/null differ diff --git a/pr-preview/pr-192/assets/fonts/Ruberoid-Light-8f6ec35a75107927e8ba62a34771c472.otf b/pr-preview/pr-192/assets/fonts/Ruberoid-Light-8f6ec35a75107927e8ba62a34771c472.otf deleted file mode 100644 index 40975aca5..000000000 Binary files a/pr-preview/pr-192/assets/fonts/Ruberoid-Light-8f6ec35a75107927e8ba62a34771c472.otf and /dev/null differ diff --git a/pr-preview/pr-192/assets/fonts/Ruberoid-Regular-3035d61dd818bff87d11c58a5560b676.otf b/pr-preview/pr-192/assets/fonts/Ruberoid-Regular-3035d61dd818bff87d11c58a5560b676.otf deleted file mode 100644 index a99fe54e3..000000000 Binary files a/pr-preview/pr-192/assets/fonts/Ruberoid-Regular-3035d61dd818bff87d11c58a5560b676.otf and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/4-856eac0d6cc770f822920d687f38f9e7.png b/pr-preview/pr-192/assets/images/4-856eac0d6cc770f822920d687f38f9e7.png deleted file mode 100644 index 8fdc4b750..000000000 Binary files a/pr-preview/pr-192/assets/images/4-856eac0d6cc770f822920d687f38f9e7.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/cca-2-d77b4e415ca0aa4499d267071d403858.png b/pr-preview/pr-192/assets/images/cca-2-d77b4e415ca0aa4499d267071d403858.png deleted file mode 100644 index 251630f43..000000000 Binary files a/pr-preview/pr-192/assets/images/cca-2-d77b4e415ca0aa4499d267071d403858.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/cca-3-11f96a3e7bbe5bc5755442e00d10040e.png b/pr-preview/pr-192/assets/images/cca-3-11f96a3e7bbe5bc5755442e00d10040e.png deleted file mode 100644 index ef51b418b..000000000 Binary files a/pr-preview/pr-192/assets/images/cca-3-11f96a3e7bbe5bc5755442e00d10040e.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/cca-54747f2736cbb93d7f0c2b52582dbb5b.png b/pr-preview/pr-192/assets/images/cca-54747f2736cbb93d7f0c2b52582dbb5b.png deleted file mode 100644 index f93f9e156..000000000 Binary files a/pr-preview/pr-192/assets/images/cca-54747f2736cbb93d7f0c2b52582dbb5b.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/comparison-table-7c865eb80a6add486978246e68eb69fa.png b/pr-preview/pr-192/assets/images/comparison-table-7c865eb80a6add486978246e68eb69fa.png deleted file mode 100644 index 252ac9095..000000000 Binary files a/pr-preview/pr-192/assets/images/comparison-table-7c865eb80a6add486978246e68eb69fa.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/lets-roll-a8b580bec3f0ea690483252f65daa0c1.jpg b/pr-preview/pr-192/assets/images/lets-roll-a8b580bec3f0ea690483252f65daa0c1.jpg deleted file mode 100644 index 72682e907..000000000 Binary files a/pr-preview/pr-192/assets/images/lets-roll-a8b580bec3f0ea690483252f65daa0c1.jpg and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/light-node-e9bf84be9327c23a6573c247e5ede7cd.png b/pr-preview/pr-192/assets/images/light-node-e9bf84be9327c23a6573c247e5ede7cd.png deleted file mode 100644 index b5cf41dd9..000000000 Binary files a/pr-preview/pr-192/assets/images/light-node-e9bf84be9327c23a6573c247e5ede7cd.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/query-a6c8042342b2de67304f474de6c0df65.gif b/pr-preview/pr-192/assets/images/query-a6c8042342b2de67304f474de6c0df65.gif deleted file mode 100644 index 5627a8338..000000000 Binary files a/pr-preview/pr-192/assets/images/query-a6c8042342b2de67304f474de6c0df65.gif and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/recipe-start-b435769158f76024880099308cda4224.gif b/pr-preview/pr-192/assets/images/recipe-start-b435769158f76024880099308cda4224.gif deleted file mode 100644 index 0a56b7eea..000000000 Binary files a/pr-preview/pr-192/assets/images/recipe-start-b435769158f76024880099308cda4224.gif and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/recipes-ed8d74ded258a73a05555483e33b0c01.gif b/pr-preview/pr-192/assets/images/recipes-ed8d74ded258a73a05555483e33b0c01.gif deleted file mode 100644 index c1e0b4abb..000000000 Binary files a/pr-preview/pr-192/assets/images/recipes-ed8d74ded258a73a05555483e33b0c01.gif and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-abci-75320e3e62c47f3eeebc5b90dd5d01d0.png b/pr-preview/pr-192/assets/images/rollkit-abci-75320e3e62c47f3eeebc5b90dd5d01d0.png deleted file mode 100644 index 2c1ee506f..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-abci-75320e3e62c47f3eeebc5b90dd5d01d0.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png b/pr-preview/pr-192/assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png deleted file mode 100644 index a6e6635f2..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-bitcoin-2-e97ee76fdc66279cd58e7e27177fcdb0.png b/pr-preview/pr-192/assets/images/rollkit-bitcoin-2-e97ee76fdc66279cd58e7e27177fcdb0.png deleted file mode 100644 index 15302188e..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-bitcoin-2-e97ee76fdc66279cd58e7e27177fcdb0.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-bitcoin-7bcecada0c85b79bf2b58ed20980d43c.png b/pr-preview/pr-192/assets/images/rollkit-bitcoin-7bcecada0c85b79bf2b58ed20980d43c.png deleted file mode 100644 index 115d5f50d..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-bitcoin-7bcecada0c85b79bf2b58ed20980d43c.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-blog-cover-8cba9a7759f1f728fb99c4bb344ef12b.png b/pr-preview/pr-192/assets/images/rollkit-blog-cover-8cba9a7759f1f728fb99c4bb344ef12b.png deleted file mode 100644 index 8634814ae..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-blog-cover-8cba9a7759f1f728fb99c4bb344ef12b.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/rollkit-lego-67992ef3767eb2c35eff95a0240749bd.png b/pr-preview/pr-192/assets/images/rollkit-lego-67992ef3767eb2c35eff95a0240749bd.png deleted file mode 100644 index dd0d72027..000000000 Binary files a/pr-preview/pr-192/assets/images/rollkit-lego-67992ef3767eb2c35eff95a0240749bd.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/transaction-flow-b70c673856a2495140120f52b31867ef.png b/pr-preview/pr-192/assets/images/transaction-flow-b70c673856a2495140120f52b31867ef.png deleted file mode 100644 index 50137bc26..000000000 Binary files a/pr-preview/pr-192/assets/images/transaction-flow-b70c673856a2495140120f52b31867ef.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/images/wordle-cd3a9ac164294b1a4acd7ffa6a63fd7b.png b/pr-preview/pr-192/assets/images/wordle-cd3a9ac164294b1a4acd7ffa6a63fd7b.png deleted file mode 100644 index cdb62ec05..000000000 Binary files a/pr-preview/pr-192/assets/images/wordle-cd3a9ac164294b1a4acd7ffa6a63fd7b.png and /dev/null differ diff --git a/pr-preview/pr-192/assets/js/01a85c17.80cbea07.js b/pr-preview/pr-192/assets/js/01a85c17.80cbea07.js deleted file mode 100644 index 487ddc154..000000000 --- a/pr-preview/pr-192/assets/js/01a85c17.80cbea07.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4013],{9058:(e,t,a)=>{a.d(t,{Z:()=>v});var l=a(7294),n=a(6010),r=a(7676),s=a(7524),c=a(9960),i=a(5999);const m="sidebar_re4s",o="sidebarItemTitle_pO2u",u="sidebarItemList_Yudw",g="sidebarItem__DBe",d="sidebarItemLink_mo7H",E="sidebarItemLinkActive_I1ZP";function b(e){let{sidebar:t}=e;return l.createElement("aside",{className:"col col--3"},l.createElement("nav",{className:(0,n.Z)(m,"thin-scrollbar"),"aria-label":(0,i.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},l.createElement("div",{className:(0,n.Z)(o,"margin-bottom--md")},t.title),l.createElement("ul",{className:(0,n.Z)(u,"clean-list")},t.items.map((e=>l.createElement("li",{key:e.permalink,className:g},l.createElement(c.Z,{isNavLink:!0,to:e.permalink,className:d,activeClassName:E},e.title)))))))}var p=a(3102);function h(e){let{sidebar:t}=e;return l.createElement("ul",{className:"menu__list"},t.items.map((e=>l.createElement("li",{key:e.permalink,className:"menu__list-item"},l.createElement(c.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title)))))}function k(e){return l.createElement(p.Zo,{component:h,props:e})}function N(e){let{sidebar:t}=e;const a=(0,s.i)();return t?.items.length?"mobile"===a?l.createElement(k,{sidebar:t}):l.createElement(b,{sidebar:t}):null}function v(e){const{sidebar:t,toc:a,children:s,...c}=e,i=t&&t.items.length>0;return l.createElement(r.Z,c,l.createElement("div",{className:"container margin-vert--lg"},l.createElement("div",{className:"row"},l.createElement(N,{sidebar:t}),l.createElement("main",{className:(0,n.Z)("col",{"col--7":i,"col--9 col--offset-1":!i}),itemScope:!0,itemType:"http://schema.org/Blog"},s),a&&l.createElement("div",{className:"col col--2"},a))))}},1223:(e,t,a)=>{a.r(t),a.d(t,{default:()=>E});var l=a(7294),n=a(6010),r=a(5999);var s=a(1944),c=a(5281),i=a(9058),m=a(3008);const o="tag_Nnez";function u(e){let{letterEntry:t}=e;return l.createElement("article",null,l.createElement("h2",null,t.letter),l.createElement("ul",{className:"padding--none"},t.tags.map((e=>l.createElement("li",{key:e.permalink,className:o},l.createElement(m.Z,e))))),l.createElement("hr",null))}function g(e){let{tags:t}=e;const a=function(e){const t={};return Object.values(e).forEach((e=>{const a=function(e){return e[0].toUpperCase()}(e.label);t[a]??=[],t[a].push(e)})),Object.entries(t).sort(((e,t)=>{let[a]=e,[l]=t;return a.localeCompare(l)})).map((e=>{let[t,a]=e;return{letter:t,tags:a.sort(((e,t)=>e.label.localeCompare(t.label)))}}))}(t);return l.createElement("section",{className:"margin-vert--lg"},a.map((e=>l.createElement(u,{key:e.letter,letterEntry:e}))))}var d=a(197);function E(e){let{tags:t,sidebar:a}=e;const m=(0,r.I)({id:"theme.tags.tagsPageTitle",message:"Tags",description:"The title of the tag list page"});return l.createElement(s.FG,{className:(0,n.Z)(c.k.wrapper.blogPages,c.k.page.blogTagsListPage)},l.createElement(s.d,{title:m}),l.createElement(d.Z,{tag:"blog_tags_list"}),l.createElement(i.Z,{sidebar:a},l.createElement("h1",null,m),l.createElement(g,{tags:t})))}},3008:(e,t,a)=>{a.d(t,{Z:()=>m});var l=a(7294),n=a(6010),r=a(9960);const s="tag_zVej",c="tagRegular_sFm0",i="tagWithCount_h2kH";function m(e){let{permalink:t,label:a,count:m}=e;return l.createElement(r.Z,{href:t,className:(0,n.Z)(s,m?i:c)},a,m&&l.createElement("span",null,m))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/0e384e19.f393c369.js b/pr-preview/pr-192/assets/js/0e384e19.f393c369.js deleted file mode 100644 index 1ff4ae7fb..000000000 --- a/pr-preview/pr-192/assets/js/0e384e19.f393c369.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9671],{3905:(e,t,o)=>{o.d(t,{Zo:()=>c,kt:()=>m});var i=o(7294);function a(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function l(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,i)}return o}function r(e){for(var t=1;t=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var s=i.createContext({}),u=function(e){var t=i.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},c=function(e){var t=u(e.components);return i.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},h=i.forwardRef((function(e,t){var o=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,c=n(e,["components","mdxType","originalType","parentName"]),p=u(o),h=a,m=p["".concat(s,".").concat(h)]||p[h]||d[h]||l;return o?i.createElement(m,r(r({ref:t},c),{},{components:o})):i.createElement(m,r({ref:t},c))}));function m(e,t){var o=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=o.length,r=new Array(l);r[0]=h;var n={};for(var s in t)hasOwnProperty.call(t,s)&&(n[s]=t[s]);n.originalType=e,n[p]="string"==typeof e?e:a,r[1]=n;for(var u=2;u{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>l,metadata:()=>n,toc:()=>u});var i=o(7462),a=(o(7294),o(3905));const l={sidebar_label:"Introduction",description:"Intro to Rollkit, a modular framework for rollups."},r="Introduction to Rollkit",n={unversionedId:"intro",id:"intro",title:"Introduction to Rollkit",description:"Intro to Rollkit, a modular framework for rollups.",source:"@site/docs/intro.md",sourceDirName:".",slug:"/intro",permalink:"/pr-preview/pr-192/docs/intro",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/intro.md",tags:[],version:"current",frontMatter:{sidebar_label:"Introduction",description:"Intro to Rollkit, a modular framework for rollups."},sidebar:"docs",next:{title:"Rollkit stack",permalink:"/pr-preview/pr-192/docs/rollkit-stack"}},s={},u=[{value:"What is Rollkit?",id:"what-is-rollkit",level:2},{value:"What problems is Rollkit solving?",id:"what-problems-is-rollkit-solving",level:2},{value:"1. Scalability and customizability",id:"1-scalability-and-customizability",level:3},{value:"2. Security and time to market",id:"2-security-and-time-to-market",level:3},{value:"Why Rollkit?",id:"why-rollkit",level:2},{value:"How can you use Rollkit?",id:"how-can-you-use-rollkit",level:2},{value:"Rollup with any execution environment",id:"rollup-with-any-execution-environment",level:3},{value:"Sovereign rollup with Cosmos SDK",id:"sovereign-rollup-with-cosmos-sdk",level:3},{value:"Build a settlement layer",id:"build-a-settlement-layer",level:3},{value:"When can you use Rollkit?",id:"when-can-you-use-rollkit",level:2}],c={toc:u};function p(e){let{components:t,...o}=e;return(0,a.kt)("wrapper",(0,i.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"introduction-to-rollkit"},"Introduction to Rollkit"),(0,a.kt)("p",null,"Welcome to Rollkit docs. We're happy you made it here!"),(0,a.kt)("p",null,"Our mission is to empower developers to quickly innovate and create entire new classes of rollups with minimal tradeoffs."),(0,a.kt)("p",null,"We're setting the bar high for developers' flexibility and ability to customize rollups however they see fit."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"In order to use Rollkit, it's important to have some\nfamiliarity with Cosmos SDK. You can get up to speed\non Cosmos SDK by visiting their ",(0,a.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main"},"official documentation page"),"."),(0,a.kt)("p",{parentName:"admonition"},"If you're familiar with Rollkit, you may want to skip to the ",(0,a.kt)("a",{parentName:"p",href:"../category/tutorials"},"tutorials section"),".")),(0,a.kt)("h2",{id:"what-is-rollkit"},"What is Rollkit?"),(0,a.kt)("p",null,"Rollkit is a rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation."),(0,a.kt)("p",null,"The Rollkit framework features a modular node that can run rollups and exposes an ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/cometbft/cometbft/tree/main/abci"},"ABCI"),"-compatible client interface, which can be used as a substitute for Tendermint in any ABCI-compatible blockchain application.\nBy default, the node utilizes Celestia as the data availability (DA) layer, however other data availability layers can be integrated."),(0,a.kt)("p",null,"Rollkit can currently be used to deploy ",(0,a.kt)("a",{parentName:"p",href:"https://blog.celestia.org/sovereign-rollup-chains/"},"sovereign rollups")," or sovereign settlement layers. In the future, we intend to support settled (not sovereign) rollups that settle to another settlement layer."),(0,a.kt)("p",null,"Rollkit is built as an open-source framework, so that developers can easily modify it to suit their applications."),(0,a.kt)("p",null,"Our goal is to empower developers to quickly innovate and create new classes of rollups with minimal trade-offs, and to make deploying a new chain as easy as deploying a smart contract."),(0,a.kt)("h2",{id:"what-problems-is-rollkit-solving"},"What problems is Rollkit solving?"),(0,a.kt)("h3",{id:"1-scalability-and-customizability"},"1. Scalability and customizability"),(0,a.kt)("p",null,"Deploying your decentralized application as a smart contract on a shared blockchain has many limitations. Your smart contract has to share computational resources with every other application, so scalability is limited."),(0,a.kt)("p",null,"Plus, you're restricted to the execution environment that the shared blockchain uses, so developer flexibility is limited."),(0,a.kt)("h3",{id:"2-security-and-time-to-market"},"2. Security and time to market"),(0,a.kt)("p",null,"Deploying a new chain might sound like the perfect solution for the problems listed above. While it's somewhat true, deploying a new layer 1 chain presents a complex set of challenges and trade-offs for developers looking to build blockchain products."),(0,a.kt)("p",null,"Deploying a new layer 1 requires significant resources, including time, capital, and expertise, which can be a barrier to entry for some developers."),(0,a.kt)("p",null,"In order to secure the network, developers must bootstrap a sufficiently secure set of validators, incurring the overhead of managing a full consensus network. This requires paying validators with inflationary tokens, putting the business sustainability of the network at risk. A strong community and network effect are also critical for success, but can be challenging to achieve as the network must gain widespread adoption to be secure and valuable."),(0,a.kt)("p",null,"In a potential future with millions of chains, it's unlikely all of those chains will be able to sustainably attract a sufficiently secure and decentralized validator set."),(0,a.kt)("h2",{id:"why-rollkit"},"Why Rollkit?"),(0,a.kt)("p",null,"Rollkit solves the challenges encountered during the deployment of a smart contract or a new layer 1, by minimizing these tradeoffs through the implementation of rollup chains (rollups)."),(0,a.kt)("p",null,"With Rollkit, developers can benefit from:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Shared security"),":\nRollups inherit security from a data availability layer, by posting blocks to it. Rollups reduce the trust assumptions placed on rollup sequencers by allowing full nodes to download and verify the transactions in the blocks posted by the sequencer. For optimistic or zk rollups, in case of fraudulent blocks, full nodes can generate fraud or zk proofs, which they can share with the rest of the network, including light nodes. Our roadmap includes the ability for light clients to receive and verify proofs, so that everyday users can enjoy high security guarantees.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Scalability:"),"\nRollkit rollups are deployed on specialized data availability layers like Celestia, which directly leverages the scalability of the DA layer. Additionally, rollup transactions are executed off-chain rather than the data availability layer. This means rollups have their own dedicated computational resources, rather than sharing computational resources with other applications.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Customizability:"),"\nRollkit is built as an open source modular framework, to make it easier for developers to reuse existing components and customize their rollups. The data availability layers and execution environments used by rollups are customizable, as well as other ",(0,a.kt)("a",{parentName:"p",href:"/pr-preview/pr-192/docs/rollkit-stack"},"components in the Rollkit stack"),".")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Faster time to market:"),"\nRollkit eliminates the need to bootstrap a validator set, manage a consensus network, incur high economic costs, and face other trade-offs that come with deploying a new layer 1. Rollkit's goal is to make deploying a rollup as easy as it is to deploy a smart contract, cutting the time it takes to bring blockchain products to market from months or even years to just minutes.")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},(0,a.kt)("strong",{parentName:"p"},"Sovereignty"),": Rollkit also enables developers to deploy sovereign rollups for cases where communities require sovereignty."))),(0,a.kt)("h2",{id:"how-can-you-use-rollkit"},"How can you use Rollkit?"),(0,a.kt)("p",null,"As briefly mentioned above, Rollkit could be used in many different ways. From sovereign rollups, to settlement layers, and in the future even to L3s."),(0,a.kt)("h3",{id:"rollup-with-any-execution-environment"},"Rollup with any execution environment"),(0,a.kt)("p",null,"Rollkit gives developers the flexibility to use pre-existing ABCI-compatible state machines or create a custom state machine tailored to their rollup needs. Rollkit does not restrict the use of any specific virtual machine, allowing developers to experiment and bring innovative applications to life."),(0,a.kt)("h3",{id:"sovereign-rollup-with-cosmos-sdk"},"Sovereign rollup with Cosmos SDK"),(0,a.kt)("p",null,"Similarly to how developers utilize the Cosmos SDK to build a sovereign layer 1 chain, the Cosmos SDK could be utilized to create a Rollkit-compatible rollup chain.\nCosmos-SDK has great ",(0,a.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main"},"documentation")," and tooling that developers can leverage to learn."),(0,a.kt)("p",null,"Another possibility is taking an existing layer 1 built with the Cosmos SDK and deploying it as a Rollkit rollup. This can provide a great opportunity for experimentation and growth."),(0,a.kt)("h3",{id:"build-a-settlement-layer"},"Build a settlement layer"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://celestia.org/learn/modular-settlement-layers/settlement-in-the-modular-stack/"},"Settlement layers")," are ideal for developers who want to avoid deploying sovereign rollups. They provide a platform for rollups to verify proofs and resolve disputes.\nAdditionally, they act as a hub for rollups to facilitate trust-minimized token transfers and liquidity sharing between rollups that share the same settlement layer.\nThink of settlement layers as a special type of execution layer."),(0,a.kt)("h2",{id:"when-can-you-use-rollkit"},"When can you use Rollkit?"),(0,a.kt)("p",null,"As of today, Rollkit is still in the MVP stages. The framework currently provides a centralized sequencer, an execution interface (ABCI or Cosmos SDK), and a connection to a data availability layer (Celestia)."),(0,a.kt)("p",null,"We're currently working on implementing many new and exciting features such as light nodes and state fraud proofs."),(0,a.kt)("p",null,"Head down to the next section (",(0,a.kt)("a",{parentName:"p",href:"/pr-preview/pr-192/docs/rollkit-stack"},"Rollkit Stack"),") to learn more about what's coming for Rollkit. If you're ready to start building, you can skip to the ",(0,a.kt)("a",{parentName:"p",href:"../category/tutorials"},"Tutorials")," section."),(0,a.kt)("p",null,"Spoiler alert, whichever you choose, it's going to be a great rabbit hole!"))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/14eb3368.9bfa4e30.js b/pr-preview/pr-192/assets/js/14eb3368.9bfa4e30.js deleted file mode 100644 index 3a7d49746..000000000 --- a/pr-preview/pr-192/assets/js/14eb3368.9bfa4e30.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9817],{1986:(e,t,n)=>{n.d(t,{Z:()=>E});var a=n(7462),r=n(7294),i=n(6010),l=n(5281),s=n(3438),c=n(8596),o=n(9960),m=n(4996),d=n(5999);function u(e){return r.createElement("svg",(0,a.Z)({viewBox:"0 0 24 24"},e),r.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}const b={breadcrumbsContainer:"breadcrumbsContainer_Z_bl",breadcrumbHomeIcon:"breadcrumbHomeIcon_OVgt"};function h(e){let{children:t,href:n,isLast:a}=e;const i="breadcrumbs__link";return a?r.createElement("span",{className:i,itemProp:"name"},t):n?r.createElement(o.Z,{className:i,href:n,itemProp:"item"},r.createElement("span",{itemProp:"name"},t)):r.createElement("span",{className:i},t)}function v(e){let{children:t,active:n,index:l,addMicrodata:s}=e;return r.createElement("li",(0,a.Z)({},s&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,i.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,r.createElement("meta",{itemProp:"position",content:String(l+1)}))}function g(){const e=(0,m.Z)("/");return r.createElement("li",{className:"breadcrumbs__item"},r.createElement(o.Z,{"aria-label":(0,d.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:(0,i.Z)("breadcrumbs__link",b.breadcrumbsItemLink),href:e},r.createElement(u,{className:b.breadcrumbHomeIcon})))}function E(){const e=(0,s.s1)(),t=(0,c.Ns)();return e?r.createElement("nav",{className:(0,i.Z)(l.k.docs.docBreadcrumbs,b.breadcrumbsContainer),"aria-label":(0,d.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},r.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&r.createElement(g,null),e.map(((t,n)=>{const a=n===e.length-1;return r.createElement(v,{key:n,active:a,index:n,addMicrodata:!!t.href},r.createElement(h,{href:t.href,isLast:a},t.label))})))):null}},4228:(e,t,n)=>{n.r(t),n.d(t,{default:()=>C});var a=n(7294),r=n(1944),i=n(3438),l=n(4996),s=n(6010),c=n(9960),o=n(3919),m=n(5999);const d="cardContainer_fWXF",u="cardTitle_rnsV",b="cardDescription_PWke";function h(e){let{href:t,children:n}=e;return a.createElement(c.Z,{href:t,className:(0,s.Z)("card padding--lg",d)},n)}function v(e){let{href:t,icon:n,title:r,description:i}=e;return a.createElement(h,{href:t},a.createElement("h2",{className:(0,s.Z)("text--truncate",u),title:r},n," ",r),i&&a.createElement("p",{className:(0,s.Z)("text--truncate",b),title:i},i))}function g(e){let{item:t}=e;const n=(0,i.Wl)(t);return n?a.createElement(v,{href:n,icon:"\ud83d\uddc3\ufe0f",title:t.label,description:(0,m.I)({message:"{count} items",id:"theme.docs.DocCard.categoryDescription",description:"The default description for a category card in the generated index about how many items this category includes"},{count:t.items.length})}):null}function E(e){let{item:t}=e;const n=(0,o.Z)(t.href)?"\ud83d\udcc4\ufe0f":"\ud83d\udd17",r=(0,i.xz)(t.docId??void 0);return a.createElement(v,{href:t.href,icon:n,title:t.label,description:r?.description})}function p(e){let{item:t}=e;switch(t.type){case"link":return a.createElement(E,{item:t});case"category":return a.createElement(g,{item:t});default:throw new Error(`unknown item type ${JSON.stringify(t)}`)}}function f(e){let{className:t}=e;const n=(0,i.jA)();return a.createElement(Z,{items:n.items,className:t})}function Z(e){const{items:t,className:n}=e;if(!t)return a.createElement(f,e);const r=(0,i.MN)(t);return a.createElement("section",{className:(0,s.Z)("row",n)},r.map(((e,t)=>a.createElement("article",{key:t,className:"col col--6 margin-bottom--lg"},a.createElement(p,{item:e})))))}var N=n(49),k=n(3120),L=n(4364),_=n(1986),T=n(2503);const x="generatedIndexPage_vN6x",I="list_eTzJ",y="title_kItE";function w(e){let{categoryGeneratedIndex:t}=e;return a.createElement(r.d,{title:t.title,description:t.description,keywords:t.keywords,image:(0,l.Z)(t.image)})}function V(e){let{categoryGeneratedIndex:t}=e;const n=(0,i.jA)();return a.createElement("div",{className:x},a.createElement(k.Z,null),a.createElement(_.Z,null),a.createElement(L.Z,null),a.createElement("header",null,a.createElement(T.Z,{as:"h1",className:y},t.title),t.description&&a.createElement("p",null,t.description)),a.createElement("article",{className:"margin-top--lg"},a.createElement(Z,{items:n.items,className:I})),a.createElement("footer",{className:"margin-top--lg"},a.createElement(N.Z,{previous:t.navigation.previous,next:t.navigation.next})))}function C(e){return a.createElement(a.Fragment,null,a.createElement(w,e),a.createElement(V,e))}},49:(e,t,n)=>{n.d(t,{Z:()=>s});var a=n(7462),r=n(7294),i=n(5999),l=n(2244);function s(e){const{previous:t,next:n}=e;return r.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,i.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages navigation",description:"The ARIA label for the docs pagination"})},t&&r.createElement(l.Z,(0,a.Z)({},t,{subLabel:r.createElement(i.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),n&&r.createElement(l.Z,(0,a.Z)({},n,{subLabel:r.createElement(i.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}},4364:(e,t,n)=>{n.d(t,{Z:()=>c});var a=n(7294),r=n(6010),i=n(5999),l=n(5281),s=n(4477);function c(e){let{className:t}=e;const n=(0,s.E)();return n.badge?a.createElement("span",{className:(0,r.Z)(t,l.k.docs.docVersionBadge,"badge badge--secondary")},a.createElement(i.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label}},"Version: {versionLabel}")):null}},3120:(e,t,n)=>{n.d(t,{Z:()=>g});var a=n(7294),r=n(6010),i=n(2263),l=n(9960),s=n(5999),c=n(143),o=n(5281),m=n(373),d=n(4477);const u={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(s.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(s.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function b(e){const t=u[e.versionMetadata.banner];return a.createElement(t,e)}function h(e){let{versionLabel:t,to:n,onClick:r}=e;return a.createElement(s.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:a.createElement("b",null,a.createElement(l.Z,{to:n,onClick:r},a.createElement(s.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function v(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:l}}=(0,i.Z)(),{pluginId:s}=(0,c.gA)({failfast:!0}),{savePreferredVersionName:d}=(0,m.J)(s),{latestDocSuggestion:u,latestVersionSuggestion:v}=(0,c.Jo)(s),g=u??(E=v).docs.find((e=>e.id===E.mainDocId));var E;return a.createElement("div",{className:(0,r.Z)(t,o.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},a.createElement("div",null,a.createElement(b,{siteTitle:l,versionMetadata:n})),a.createElement("div",{className:"margin-top--md"},a.createElement(h,{versionLabel:v.label,to:g.path,onClick:()=>d(v.name)})))}function g(e){let{className:t}=e;const n=(0,d.E)();return n.banner?a.createElement(v,{className:t,versionMetadata:n}):null}},2503:(e,t,n)=>{n.d(t,{Z:()=>m});var a=n(7462),r=n(7294),i=n(6010),l=n(5999),s=n(6668);const c="anchorWithStickyNavbar_LWe7",o="anchorWithHideOnScrollNavbar_WYt5";function m(e){let{as:t,id:n,...m}=e;const{navbar:{hideOnScroll:d}}=(0,s.L)();return"h1"!==t&&n?r.createElement(t,(0,a.Z)({},m,{className:(0,i.Z)("anchor",d?o:c),id:n}),m.children,r.createElement("a",{className:"hash-link",href:`#${n}`,title:(0,l.I)({id:"theme.common.headingLinkTitle",message:"Direct link to heading",description:"Title for link to heading"})},"\u200b")):r.createElement(t,(0,a.Z)({},m,{id:void 0}))}},2244:(e,t,n)=>{n.d(t,{Z:()=>l});var a=n(7294),r=n(6010),i=n(9960);function l(e){const{permalink:t,title:n,subLabel:l,isNext:s}=e;return a.createElement(i.Z,{className:(0,r.Z)("pagination-nav__link",s?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},l&&a.createElement("div",{className:"pagination-nav__sublabel"},l),a.createElement("div",{className:"pagination-nav__label"},n))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/17010a1c.8e4a3039.js b/pr-preview/pr-192/assets/js/17010a1c.8e4a3039.js deleted file mode 100644 index eabb4366b..000000000 --- a/pr-preview/pr-192/assets/js/17010a1c.8e4a3039.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7284],{2532:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-192/blog/tags/rollkit","page":1,"postsPerPage":10,"totalPages":1,"totalCount":3,"blogDescription":"Blog","blogTitle":"Blog"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/17896441.88df801a.js b/pr-preview/pr-192/assets/js/17896441.88df801a.js deleted file mode 100644 index 56a5e2696..000000000 --- a/pr-preview/pr-192/assets/js/17896441.88df801a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7918],{1986:(e,t,n)=>{n.d(t,{Z:()=>f});var a=n(7462),l=n(7294),r=n(6010),s=n(5281),o=n(3438),c=n(8596),i=n(9960),d=n(4996),m=n(5999);function u(e){return l.createElement("svg",(0,a.Z)({viewBox:"0 0 24 24"},e),l.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}const v={breadcrumbsContainer:"breadcrumbsContainer_Z_bl",breadcrumbHomeIcon:"breadcrumbHomeIcon_OVgt"};function b(e){let{children:t,href:n,isLast:a}=e;const r="breadcrumbs__link";return a?l.createElement("span",{className:r,itemProp:"name"},t):n?l.createElement(i.Z,{className:r,href:n,itemProp:"item"},l.createElement("span",{itemProp:"name"},t)):l.createElement("span",{className:r},t)}function h(e){let{children:t,active:n,index:s,addMicrodata:o}=e;return l.createElement("li",(0,a.Z)({},o&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,r.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,l.createElement("meta",{itemProp:"position",content:String(s+1)}))}function p(){const e=(0,d.Z)("/");return l.createElement("li",{className:"breadcrumbs__item"},l.createElement(i.Z,{"aria-label":(0,m.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:(0,r.Z)("breadcrumbs__link",v.breadcrumbsItemLink),href:e},l.createElement(u,{className:v.breadcrumbHomeIcon})))}function f(){const e=(0,o.s1)(),t=(0,c.Ns)();return e?l.createElement("nav",{className:(0,r.Z)(s.k.docs.docBreadcrumbs,v.breadcrumbsContainer),"aria-label":(0,m.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},l.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&l.createElement(p,null),e.map(((t,n)=>{const a=n===e.length-1;return l.createElement(h,{key:n,active:a,index:n,addMicrodata:!!t.href},l.createElement(b,{href:t.href,isLast:a},t.label))})))):null}},5154:(e,t,n)=>{n.r(t),n.d(t,{default:()=>J});var a=n(7294),l=n(1944),r=n(902);const s=a.createContext(null);function o(e){let{children:t,content:n}=e;const l=function(e){return(0,a.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return a.createElement(s.Provider,{value:l},t)}function c(){const e=(0,a.useContext)(s);if(null===e)throw new r.i6("DocProvider");return e}function i(){const{metadata:e,frontMatter:t,assets:n}=c();return a.createElement(l.d,{title:e.title,description:e.description,keywords:t.keywords,image:n.image??t.image})}var d=n(6010),m=n(7524),u=n(49);function v(){const{metadata:e}=c();return a.createElement(u.Z,{previous:e.previous,next:e.next})}var b=n(3120),h=n(4364),p=n(5281),f=n(5999);function E(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n}=e;return a.createElement(f.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:a.createElement("b",null,a.createElement("time",{dateTime:new Date(1e3*t).toISOString()},n))}}," on {date}")}function g(e){let{lastUpdatedBy:t}=e;return a.createElement(f.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:a.createElement("b",null,t)}}," by {user}")}function L(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n,lastUpdatedBy:l}=e;return a.createElement("span",{className:p.k.common.lastUpdated},a.createElement(f.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?a.createElement(E,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:l?a.createElement(g,{lastUpdatedBy:l}):""}},"Last updated{atDate}{byUser}"),!1)}var N=n(4881),Z=n(1526);const k="lastUpdated_vwxv";function _(e){return a.createElement("div",{className:(0,d.Z)(p.k.docs.docFooterTagsRow,"row margin-bottom--sm")},a.createElement("div",{className:"col"},a.createElement(Z.Z,e)))}function C(e){let{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:l,formattedLastUpdatedAt:r}=e;return a.createElement("div",{className:(0,d.Z)(p.k.docs.docFooterEditMetaRow,"row")},a.createElement("div",{className:"col"},t&&a.createElement(N.Z,{editUrl:t})),a.createElement("div",{className:(0,d.Z)("col",k)},(n||l)&&a.createElement(L,{lastUpdatedAt:n,formattedLastUpdatedAt:r,lastUpdatedBy:l})))}function T(){const{metadata:e}=c(),{editUrl:t,lastUpdatedAt:n,formattedLastUpdatedAt:l,lastUpdatedBy:r,tags:s}=e,o=s.length>0,i=!!(t||n||r);return o||i?a.createElement("footer",{className:(0,d.Z)(p.k.docs.docFooter,"docusaurus-mt-lg")},o&&a.createElement(_,{tags:s}),i&&a.createElement(C,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:r,formattedLastUpdatedAt:l})):null}var x=n(6043),H=n(3743),U=n(7462);const y="tocCollapsibleButton_TO0P",A="tocCollapsibleButtonExpanded_MG3E";function w(e){let{collapsed:t,...n}=e;return a.createElement("button",(0,U.Z)({type:"button"},n,{className:(0,d.Z)("clean-btn",y,!t&&A,n.className)}),a.createElement(f.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component"},"On this page"))}const M="tocCollapsible_ETCw",I="tocCollapsibleContent_vkbj",B="tocCollapsibleExpanded_sAul";function O(e){let{toc:t,className:n,minHeadingLevel:l,maxHeadingLevel:r}=e;const{collapsed:s,toggleCollapsed:o}=(0,x.u)({initialState:!0});return a.createElement("div",{className:(0,d.Z)(M,!s&&B,n)},a.createElement(w,{collapsed:s,onClick:o}),a.createElement(x.z,{lazy:!0,className:I,collapsed:s},a.createElement(H.Z,{toc:t,minHeadingLevel:l,maxHeadingLevel:r})))}const V="tocMobile_ITEo";function S(){const{toc:e,frontMatter:t}=c();return a.createElement(O,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,d.Z)(p.k.docs.docTocMobile,V)})}var D=n(9407);function P(){const{toc:e,frontMatter:t}=c();return a.createElement(D.Z,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:p.k.docs.docTocDesktop})}var R=n(2503),z=n(210);function F(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=c();return t.hide_title||void 0!==n?null:e.title}();return a.createElement("div",{className:(0,d.Z)(p.k.docs.docMarkdown,"markdown")},n&&a.createElement("header",null,a.createElement(R.Z,{as:"h1"},n)),a.createElement(z.Z,null,t))}var j=n(1986);const q="docItemContainer_Djhp",$="docItemCol_VOVn";function G(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=c(),n=(0,m.i)(),l=e.hide_table_of_contents,r=!l&&t.length>0;return{hidden:l,mobile:r?a.createElement(S,null):void 0,desktop:!r||"desktop"!==n&&"ssr"!==n?void 0:a.createElement(P,null)}}();return a.createElement("div",{className:"row"},a.createElement("div",{className:(0,d.Z)("col",!n.hidden&&$)},a.createElement(b.Z,null),a.createElement("div",{className:q},a.createElement("article",null,a.createElement(j.Z,null),a.createElement(h.Z,null),n.mobile,a.createElement(F,null,t),a.createElement(T,null)),a.createElement(v,null))),n.desktop&&a.createElement("div",{className:"col col--3"},n.desktop))}function J(e){const t=`docs-doc-id-${e.content.metadata.unversionedId}`,n=e.content;return a.createElement(o,{content:e.content},a.createElement(l.FG,{className:t},a.createElement(i,null),a.createElement(G,null,a.createElement(n,null))))}},49:(e,t,n)=>{n.d(t,{Z:()=>o});var a=n(7462),l=n(7294),r=n(5999),s=n(2244);function o(e){const{previous:t,next:n}=e;return l.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,r.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages navigation",description:"The ARIA label for the docs pagination"})},t&&l.createElement(s.Z,(0,a.Z)({},t,{subLabel:l.createElement(r.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),n&&l.createElement(s.Z,(0,a.Z)({},n,{subLabel:l.createElement(r.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}},4364:(e,t,n)=>{n.d(t,{Z:()=>c});var a=n(7294),l=n(6010),r=n(5999),s=n(5281),o=n(4477);function c(e){let{className:t}=e;const n=(0,o.E)();return n.badge?a.createElement("span",{className:(0,l.Z)(t,s.k.docs.docVersionBadge,"badge badge--secondary")},a.createElement(r.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label}},"Version: {versionLabel}")):null}},3120:(e,t,n)=>{n.d(t,{Z:()=>p});var a=n(7294),l=n(6010),r=n(2263),s=n(9960),o=n(5999),c=n(143),i=n(5281),d=n(373),m=n(4477);const u={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(o.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(o.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function v(e){const t=u[e.versionMetadata.banner];return a.createElement(t,e)}function b(e){let{versionLabel:t,to:n,onClick:l}=e;return a.createElement(o.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:a.createElement("b",null,a.createElement(s.Z,{to:n,onClick:l},a.createElement(o.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function h(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:s}}=(0,r.Z)(),{pluginId:o}=(0,c.gA)({failfast:!0}),{savePreferredVersionName:m}=(0,d.J)(o),{latestDocSuggestion:u,latestVersionSuggestion:h}=(0,c.Jo)(o),p=u??(f=h).docs.find((e=>e.id===f.mainDocId));var f;return a.createElement("div",{className:(0,l.Z)(t,i.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},a.createElement("div",null,a.createElement(v,{siteTitle:s,versionMetadata:n})),a.createElement("div",{className:"margin-top--md"},a.createElement(b,{versionLabel:h.label,to:p.path,onClick:()=>m(h.name)})))}function p(e){let{className:t}=e;const n=(0,m.E)();return n.banner?a.createElement(h,{className:t,versionMetadata:n}):null}},9407:(e,t,n)=>{n.d(t,{Z:()=>c});var a=n(7462),l=n(7294),r=n(6010),s=n(3743);const o="tableOfContents_bqdL";function c(e){let{className:t,...n}=e;return l.createElement("div",{className:(0,r.Z)(o,"thin-scrollbar",t)},l.createElement(s.Z,(0,a.Z)({},n,{linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})))}},3743:(e,t,n)=>{n.d(t,{Z:()=>b});var a=n(7462),l=n(7294),r=n(6668);function s(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const a=n.slice(2,e.level);e.parentIndex=Math.max(...a),n[e.level]=t}));const a=[];return t.forEach((e=>{const{parentIndex:n,...l}=e;n>=0?t[n].children.push(l):a.push(l)})),a}function o(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return t.flatMap((e=>{const t=o({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[{...e,children:t}]:t}))}function c(e){const t=e.getBoundingClientRect();return t.top===t.bottom?c(e.parentNode):t}function i(e,t){let{anchorTopOffset:n}=t;const a=e.find((e=>c(e).top>=n));if(a){return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function m(e){const t=(0,l.useRef)(void 0),n=d();(0,l.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:a,linkActiveClassName:l,minHeadingLevel:r,maxHeadingLevel:s}=e;function o(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(a),o=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const a=[];for(let l=t;l<=n;l+=1)a.push(`h${l}.anchor`);return Array.from(document.querySelectorAll(a.join()))}({minHeadingLevel:r,maxHeadingLevel:s}),c=i(o,{anchorTopOffset:n.current}),d=e.find((e=>c&&c.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(l),e.classList.add(l),t.current=e):e.classList.remove(l)}(e,e===d)}))}return document.addEventListener("scroll",o),document.addEventListener("resize",o),o(),()=>{document.removeEventListener("scroll",o),document.removeEventListener("resize",o)}}),[e,n])}function u(e){let{toc:t,className:n,linkClassName:a,isChild:r}=e;return t.length?l.createElement("ul",{className:r?void 0:n},t.map((e=>l.createElement("li",{key:e.id},l.createElement("a",{href:`#${e.id}`,className:a??void 0,dangerouslySetInnerHTML:{__html:e.value}}),l.createElement(u,{isChild:!0,toc:e.children,className:n,linkClassName:a}))))):null}const v=l.memo(u);function b(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:c="table-of-contents__link",linkActiveClassName:i,minHeadingLevel:d,maxHeadingLevel:u,...b}=e;const h=(0,r.L)(),p=d??h.tableOfContents.minHeadingLevel,f=u??h.tableOfContents.maxHeadingLevel,E=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,l.useMemo)((()=>o({toc:s(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:p,maxHeadingLevel:f});return m((0,l.useMemo)((()=>{if(c&&i)return{linkClassName:c,linkActiveClassName:i,minHeadingLevel:p,maxHeadingLevel:f}}),[c,i,p,f])),l.createElement(v,(0,a.Z)({toc:E,className:n,linkClassName:c},b))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/1be78505.fa749a32.js b/pr-preview/pr-192/assets/js/1be78505.fa749a32.js deleted file mode 100644 index fea2c31bd..000000000 --- a/pr-preview/pr-192/assets/js/1be78505.fa749a32.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9514,4972],{9963:(e,t,n)=>{n.r(t),n.d(t,{default:()=>Ie});var a=n(7294),l=n(6010),o=n(1944),r=n(5281),c=n(3320),i=n(3438),s=n(4477),d=n(1116),m=n(7676),u=n(5999),b=n(2466),p=n(5936);const h="backToTopButton_sjWU",E="backToTopButtonShow_xfvO";function f(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,l]=(0,a.useState)(!1),o=(0,a.useRef)(!1),{startScroll:r,cancelScroll:c}=(0,b.Ct)();return(0,b.RF)(((e,n)=>{let{scrollY:a}=e;const r=n?.scrollY;r&&(o.current?o.current=!1:a>=r?(c(),l(!1)):a{e.location.hash&&(o.current=!0,l(!1))})),{shown:n,scrollToTop:()=>r(0)}}({threshold:300});return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,l.Z)("clean-btn",r.k.common.backToTopButton,h,e&&E),type:"button",onClick:t})}var g=n(6550),_=n(7524),v=n(6668),k=n(1327),C=n(7462);function I(e){return a.createElement("svg",(0,C.Z)({width:"20",height:"20","aria-hidden":"true"},e),a.createElement("g",{fill:"#7a7a7a"},a.createElement("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),a.createElement("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})))}const N="collapseSidebarButton_PEFL",S="collapseSidebarButtonIcon_kv0_";function Z(e){let{onClick:t}=e;return a.createElement("button",{type:"button",title:(0,u.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,l.Z)("button button--secondary button--outline",N),onClick:t},a.createElement(I,{className:S}))}var y=n(9689),T=n(902);const x=Symbol("EmptyContext"),L=a.createContext(x);function w(e){let{children:t}=e;const[n,l]=(0,a.useState)(null),o=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:l})),[n]);return a.createElement(L.Provider,{value:o},t)}var M=n(6043),A=n(8596),B=n(9960),F=n(2389);function H(e){let{categoryLabel:t,onClick:n}=e;return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel",message:"Toggle the collapsible sidebar category '{label}'",description:"The ARIA label to toggle the collapsible sidebar category"},{label:t}),type:"button",className:"clean-btn menu__caret",onClick:n})}function P(e){let{item:t,onItemClick:n,activePath:o,level:c,index:s,...d}=e;const{items:m,label:u,collapsible:b,className:p,href:h}=t,{docs:{sidebar:{autoCollapseCategories:E}}}=(0,v.L)(),f=function(e){const t=(0,F.Z)();return(0,a.useMemo)((()=>e.href?e.href:!t&&e.collapsible?(0,i.Wl)(e):void 0),[e,t])}(t),g=(0,i._F)(t,o),_=(0,A.Mg)(h,o),{collapsed:k,setCollapsed:I}=(0,M.u)({initialState:()=>!!b&&(!g&&t.collapsed)}),{expandedItem:N,setExpandedItem:S}=function(){const e=(0,a.useContext)(L);if(e===x)throw new T.i6("DocSidebarItemsExpandedStateProvider");return e}(),Z=function(e){void 0===e&&(e=!k),S(e?null:s),I(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:l}=e;const o=(0,T.D9)(t);(0,a.useEffect)((()=>{t&&!o&&n&&l(!1)}),[t,o,n,l])}({isActive:g,collapsed:k,updateCollapsed:Z}),(0,a.useEffect)((()=>{b&&null!=N&&N!==s&&E&&I(!0)}),[b,N,s,I,E]),a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemCategory,r.k.docs.docSidebarItemCategoryLevel(c),"menu__list-item",{"menu__list-item--collapsed":k},p)},a.createElement("div",{className:(0,l.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":_})},a.createElement(B.Z,(0,C.Z)({className:(0,l.Z)("menu__link",{"menu__link--sublist":b,"menu__link--sublist-caret":!h&&b,"menu__link--active":g}),onClick:b?e=>{n?.(t),h?Z(!1):(e.preventDefault(),Z())}:()=>{n?.(t)},"aria-current":_?"page":void 0,"aria-expanded":b?!k:void 0,href:b?f??"#":f},d),u),h&&b&&a.createElement(H,{categoryLabel:u,onClick:e=>{e.preventDefault(),Z()}})),a.createElement(M.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:k},a.createElement(G,{items:m,tabIndex:k?-1:0,onItemClick:n,activePath:o,level:c+1})))}var W=n(3919),D=n(9471);const R="menuExternalLink_NmtK";function z(e){let{item:t,onItemClick:n,activePath:o,level:c,index:s,...d}=e;const{href:m,label:u,className:b,autoAddBaseUrl:p}=t,h=(0,i._F)(t,o),E=(0,W.Z)(m);return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(c),"menu__list-item",b),key:u},a.createElement(B.Z,(0,C.Z)({className:(0,l.Z)("menu__link",!E&&R,{"menu__link--active":h}),autoAddBaseUrl:p,"aria-current":h?"page":void 0,to:m},E&&{onClick:n?()=>n(t):void 0},d),u,!E&&a.createElement(D.Z,null)))}const U="menuHtmlItem_M9Kj";function K(e){let{item:t,level:n,index:o}=e;const{value:c,defaultStyle:i,className:s}=t;return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(n),i&&[U,"menu__list-item"],s),key:o,dangerouslySetInnerHTML:{__html:c}})}function V(e){let{item:t,...n}=e;switch(t.type){case"category":return a.createElement(P,(0,C.Z)({item:t},n));case"html":return a.createElement(K,(0,C.Z)({item:t},n));default:return a.createElement(z,(0,C.Z)({item:t},n))}}function j(e){let{items:t,...n}=e;return a.createElement(w,null,t.map(((e,t)=>a.createElement(V,(0,C.Z)({key:t,item:e,index:t},n)))))}const G=(0,a.memo)(j),Y="menu_SIkG",q="menuWithAnnouncementBar_GW3s";function O(e){let{path:t,sidebar:n,className:o}=e;const c=function(){const{isActive:e}=(0,y.nT)(),[t,n]=(0,a.useState)(e);return(0,b.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return a.createElement("nav",{className:(0,l.Z)("menu thin-scrollbar",Y,c&&q,o)},a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(G,{items:n,activePath:t,level:1})))}const X="sidebar_njMd",J="sidebarWithHideableNavbar_wUlq",Q="sidebarHidden_VK0M",$="sidebarLogo_isFc";function ee(e){let{path:t,sidebar:n,onCollapse:o,isHidden:r}=e;const{navbar:{hideOnScroll:c},docs:{sidebar:{hideable:i}}}=(0,v.L)();return a.createElement("div",{className:(0,l.Z)(X,c&&J,r&&Q)},c&&a.createElement(k.Z,{tabIndex:-1,className:$}),a.createElement(O,{path:t,sidebar:n}),i&&a.createElement(Z,{onClick:o}))}const te=a.memo(ee);var ne=n(3102),ae=n(2961);const le=e=>{let{sidebar:t,path:n}=e;const o=(0,ae.e)();return a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(G,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&o.toggle(),"link"===e.type&&o.toggle()},level:1}))};function oe(e){return a.createElement(ne.Zo,{component:le,props:e})}const re=a.memo(oe);function ce(e){const t=(0,_.i)(),n="desktop"===t||"ssr"===t,l="mobile"===t;return a.createElement(a.Fragment,null,n&&a.createElement(te,e),l&&a.createElement(re,e))}const ie="expandButton_m80_",se="expandButtonIcon_BlDH";function de(e){let{toggleSidebar:t}=e;return a.createElement("div",{className:ie,title:(0,u.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t},a.createElement(I,{className:se}))}const me="docSidebarContainer_b6E3",ue="docSidebarContainerHidden_b3ry";function be(e){let{children:t}=e;const n=(0,d.V)();return a.createElement(a.Fragment,{key:n?.name??"noSidebar"},t)}function pe(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:o}=e;const{pathname:c}=(0,g.TH)(),[i,s]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{i&&s(!1),o((e=>!e))}),[o,i]);return a.createElement("aside",{className:(0,l.Z)(r.k.docs.docSidebarContainer,me,n&&ue),onTransitionEnd:e=>{e.currentTarget.classList.contains(me)&&n&&s(!0)}},a.createElement(be,null,a.createElement(ce,{sidebar:t,path:c,onCollapse:d,isHidden:i})),i&&a.createElement(de,{toggleSidebar:d}))}const he={docMainContainer:"docMainContainer_gTbr",docMainContainerEnhanced:"docMainContainerEnhanced_Uz_u",docItemWrapperEnhanced:"docItemWrapperEnhanced_czyv"};function Ee(e){let{hiddenSidebarContainer:t,children:n}=e;const o=(0,d.V)();return a.createElement("main",{className:(0,l.Z)(he.docMainContainer,(t||!o)&&he.docMainContainerEnhanced)},a.createElement("div",{className:(0,l.Z)("container padding-top--md padding-bottom--lg",he.docItemWrapper,t&&he.docItemWrapperEnhanced)},n))}const fe="docPage__5DB",ge="docsWrapper_BCFX";function _e(e){let{children:t}=e;const n=(0,d.V)(),[l,o]=(0,a.useState)(!1);return a.createElement(m.Z,{wrapperClassName:ge},a.createElement(f,null),a.createElement("div",{className:fe},n&&a.createElement(pe,{sidebar:n.items,hiddenSidebarContainer:l,setHiddenSidebarContainer:o}),a.createElement(Ee,{hiddenSidebarContainer:l},t)))}var ve=n(4972),ke=n(197);function Ce(e){const{versionMetadata:t}=e;return a.createElement(a.Fragment,null,a.createElement(ke.Z,{version:t.version,tag:(0,c.os)(t.pluginId,t.version)}),a.createElement(o.d,null,t.noIndex&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"})))}function Ie(e){const{versionMetadata:t}=e,n=(0,i.hI)(e);if(!n)return a.createElement(ve.default,null);const{docElement:c,sidebarName:m,sidebarItems:u}=n;return a.createElement(a.Fragment,null,a.createElement(Ce,e),a.createElement(o.FG,{className:(0,l.Z)(r.k.wrapper.docsPages,r.k.page.docsDocPage,e.versionMetadata.className)},a.createElement(s.q,{version:t},a.createElement(d.b,{name:m,items:u},a.createElement(_e,null,c)))))}},4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>c});var a=n(7294),l=n(5999),o=n(1944),r=n(7676);function c(){return a.createElement(a.Fragment,null,a.createElement(o.d,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/1c091541.60b718c6.js b/pr-preview/pr-192/assets/js/1c091541.60b718c6.js deleted file mode 100644 index 77e15b4eb..000000000 --- a/pr-preview/pr-192/assets/js/1c091541.60b718c6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8271],{4469:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-blog","id":"default"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/1df93b7f.dc76c62a.js b/pr-preview/pr-192/assets/js/1df93b7f.dc76c62a.js deleted file mode 100644 index 517ca61d3..000000000 --- a/pr-preview/pr-192/assets/js/1df93b7f.dc76c62a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3237],{9872:(e,t,a)=>{a.d(t,{Z:()=>o});var l,n,r,c=a(7294);function i(){return i=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{title:t,titleId:a,...o}=e;return c.createElement("svg",i({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36","aria-labelledby":a},o),t?c.createElement("title",{id:a},t):null,l||(l=c.createElement("path",{fill:"#CCD6DD",d:"M31 2H5a3 3 0 0 0-3 3v26a3 3 0 0 0 3 3h26a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3z"})),n||(n=c.createElement("path",{fill:"#E1E8ED",d:"M31 1H5a4 4 0 0 0-4 4v26a4 4 0 0 0 4 4h26a4 4 0 0 0 4-4V5a4 4 0 0 0-4-4zm0 2c1.103 0 2 .897 2 2v4h-6V3h4zm-4 16h6v6h-6v-6zm0-2v-6h6v6h-6zM25 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM17 3v6h-6V3h6zm-6 8h6v6h-6v-6zm0 8h6v6h-6v-6zM3 5c0-1.103.897-2 2-2h4v6H3V5zm0 6h6v6H3v-6zm0 8h6v6H3v-6zm2 14c-1.103 0-2-.897-2-2v-4h6v6H5zm6 0v-6h6v6h-6zm8 0v-6h6v6h-6zm12 0h-4v-6h6v4c0 1.103-.897 2-2 2z"})),r||(r=c.createElement("path",{fill:"#DD2E44",d:"M4.998 33a2 2 0 0 1-1.759-2.948l7-13a1.999 1.999 0 0 1 3.175-.466l6.076 6.076 9.738-18.59a2 2 0 0 1 3.543 1.857l-11 21a2.002 2.002 0 0 1-1.47 1.05 2.017 2.017 0 0 1-1.716-.563l-6.1-6.099-5.724 10.631A2 2 0 0 1 4.998 33z"})))}},6350:(e,t,a)=>{a.d(t,{Z:()=>r});var l=a(7294);function n(){return n=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{title:t,titleId:a,...r}=e;return l.createElement("svg",n({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36",style:{enableBackground:"new 0 0 36 36"},xmlSpace:"preserve","aria-labelledby":a},r),t?l.createElement("title",{id:a},t):null,l.createElement("path",{d:"M18 1.5c-5.5 0-10 4.5-10 10v10h4v-10c0-3.3 2.7-6 6-6s6 2.7 6 6v10h4v-10c0-5.5-4.5-10-10-10z",style:{fill:"#aab8c2"}}),l.createElement("path",{d:"M31 30.5c0 2.2-1.8 4-4 4H9c-2.2 0-4-1.8-4-4v-12c0-2.2 1.8-4 4-4h18c2.2 0 4 1.8 4 4v12z",style:{fill:"#ffac33"}}))}},4745:(e,t,a)=>{a.d(t,{Z:()=>h});var l,n,r,c,i,o,s=a(7294);function m(){return m=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{title:t,titleId:a,...h}=e;return s.createElement("svg",m({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36","aria-labelledby":a},h),t?s.createElement("title",{id:a},t):null,l||(l=s.createElement("path",{fill:"#A0041E",d:"m1 17 8-7 16 1 1 16-7 8s.001-5.999-6-12-12-6-12-6z"})),n||(n=s.createElement("path",{fill:"#FFAC33",d:"M.973 35s-.036-7.979 2.985-11S15 21.187 15 21.187 14.999 29 11.999 32c-3 3-11.026 3-11.026 3z"})),r||(r=s.createElement("circle",{fill:"#FFCC4D",cx:8.999,cy:27,r:4})),c||(c=s.createElement("path",{fill:"#55ACEE",d:"M35.999 0s-10 0-22 10c-6 5-6 14-4 16s11 2 16-4c10-12 10-22 10-22z"})),i||(i=s.createElement("path",{d:"M26.999 5a3.996 3.996 0 0 0-3.641 2.36A3.969 3.969 0 0 1 24.999 7a4 4 0 0 1 4 4c0 .586-.133 1.139-.359 1.64A3.993 3.993 0 0 0 30.999 9a4 4 0 0 0-4-4z"})),o||(o=s.createElement("path",{fill:"#A0041E",d:"M8 28s0-4 1-5 13.001-10.999 14-10-9.001 13-10.001 14S8 28 8 28z"})))}},5836:(e,t,a)=>{a.d(t,{Z:()=>c});var l,n=a(7294);function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let{title:t,titleId:a,...c}=e;return n.createElement("svg",r({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36","aria-labelledby":a},c),t?n.createElement("title",{id:a},t):null,l||(l=n.createElement("path",{fill:"#66757F",d:"M34 15h-3.362a12.915 12.915 0 0 0-1.582-3.814l2.379-2.379a2 2 0 0 0 0-2.829l-1.414-1.414a2 2 0 0 0-2.828 0l-2.379 2.379A12.924 12.924 0 0 0 21 5.362V2a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v3.362a12.915 12.915 0 0 0-3.814 1.582L8.808 4.565a2 2 0 0 0-2.828 0L4.565 5.979a2.002 2.002 0 0 0-.001 2.829l2.379 2.379A12.918 12.918 0 0 0 5.362 15H2a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h3.362a12.92 12.92 0 0 0 1.582 3.813l-2.379 2.379c-.78.78-.78 2.048.001 2.829l1.414 1.414c.78.78 2.047.78 2.828 0l2.379-2.379a12.889 12.889 0 0 0 3.814 1.582V34a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-3.362a12.92 12.92 0 0 0 3.813-1.582l2.379 2.379a2 2 0 0 0 2.828 0l1.414-1.414a2 2 0 0 0 0-2.829l-2.379-2.379a12.889 12.889 0 0 0 1.582-3.814H34a2 2 0 0 0 2-2v-2A2 2 0 0 0 34 15zM18 26a8 8 0 1 1 0-16 8 8 0 0 1 0 16z"})))}},8391:(e,t,a)=>{a.r(t),a.d(t,{default:()=>f});var l=a(7294),n=a(6010),r=a(9960),c=a(2263),i=a(7676),o=a(7462);const s="features_t9lD",m="featureSvg_GfXr",h=[{title:"Shared security",Svg:a(6350).Z,description:l.createElement(l.Fragment,null,"Rollups inherit security from the consensus and data availability layer")},{title:"Scalable",Svg:a(9872).Z,description:l.createElement(l.Fragment,null,"With off-chain execution, rollups have their own dedicated computational resources")},{title:"Flexible",Svg:a(5836).Z,description:l.createElement(l.Fragment,null,"Freedom to configure the execution environment and other components")},{title:"Easy to deploy",Svg:a(4745).Z,description:l.createElement(l.Fragment,null,"Deploy a rollup with only a few terminal commands")}];function v(e){let{title:t,Svg:a,description:r}=e;return l.createElement("div",{className:(0,n.Z)("col col--3")},l.createElement("div",{className:"text--center"},l.createElement(a,{className:m,role:"img"})),l.createElement("div",{className:"text--center padding-horiz--md"},l.createElement("h3",null,t),l.createElement("p",null,r)))}function d(){return l.createElement("section",{className:s},l.createElement("div",{className:"container"},l.createElement("div",{className:"row"},h.map(((e,t)=>l.createElement(v,(0,o.Z)({key:t},e)))))))}const u="heroBanner_qdFl",p="buttons_AeoN";function E(){const{siteConfig:e}=(0,c.Z)();return l.createElement("header",{className:(0,n.Z)("hero hero--primary",u)},l.createElement("div",{className:"container"},l.createElement("h1",{className:"hero__title"},e.tagline),l.createElement("div",{className:p},l.createElement(r.Z,{className:"front-page-link",to:"/docs/intro/"},l.createElement("p",{className:"button-heading"},"Intro"),"Learn how Rollkit works"),l.createElement(r.Z,{className:"front-page-link",to:"/docs/rollkit-stack/"},l.createElement("p",{className:"button-heading"},"Concepts"),"Learn about the stack"),l.createElement(r.Z,{className:"front-page-link",to:"/docs/tutorials/gm-world/"},l.createElement("p",{className:"button-heading"},"Build a rollup"),"Deploy a rollup with Rollkit"))))}function f(){const{siteConfig:e}=(0,c.Z)();return l.createElement(i.Z,{title:`Build modular with ${e.title}`,description:"A modular framework for rollups."},l.createElement(E,null),l.createElement("main",null,l.createElement(d,null)))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/21d57c30.5ce19e6b.js b/pr-preview/pr-192/assets/js/21d57c30.5ce19e6b.js deleted file mode 100644 index 371393ab5..000000000 --- a/pr-preview/pr-192/assets/js/21d57c30.5ce19e6b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6592],{9484:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-192/blog","page":1,"postsPerPage":10,"totalPages":1,"totalCount":3,"blogDescription":"Blog","blogTitle":"Blog"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/247783bb.dadfb5a6.js b/pr-preview/pr-192/assets/js/247783bb.dadfb5a6.js deleted file mode 100644 index fd96dba6d..000000000 --- a/pr-preview/pr-192/assets/js/247783bb.dadfb5a6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9334],{3769:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/2952c598.58be34ab.js b/pr-preview/pr-192/assets/js/2952c598.58be34ab.js deleted file mode 100644 index 4eebe70e4..000000000 --- a/pr-preview/pr-192/assets/js/2952c598.58be34ab.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7087],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>h});var a=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=a.createContext({}),p=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(s.Provider,{value:n},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=p(t),m=o,h=d["".concat(s,".").concat(m)]||d[m]||u[m]||r;return t?a.createElement(h,l(l({ref:n},c),{},{components:t})):a.createElement(h,l({ref:n},c))}));function h(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var r=t.length,l=new Array(r);l[0]=m;var i={};for(var s in n)hasOwnProperty.call(n,s)&&(i[s]=n[s]);i.originalType=e,i[d]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>r,metadata:()=>i,toc:()=>p});var a=t(7462),o=(t(7294),t(3905));const r={sidebar_label:"GM world frontend tutorial",description:"Build a frontend for your Rollkit rollup locally."},l="GM world frontend tutorial",i={unversionedId:"tutorials/gm-world-frontend",id:"tutorials/gm-world-frontend",title:"GM world frontend tutorial",description:"Build a frontend for your Rollkit rollup locally.",source:"@site/docs/tutorials/gm-world-frontend.md",sourceDirName:"tutorials",slug:"/tutorials/gm-world-frontend",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world-frontend",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/gm-world-frontend.md",tags:[],version:"current",frontMatter:{sidebar_label:"GM world frontend tutorial",description:"Build a frontend for your Rollkit rollup locally."},sidebar:"docs",previous:{title:"GM world tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world"},next:{title:"Recipe book tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/recipe-book"}},s={},p=[{value:"Getting started",id:"getting-started",level:2},{value:"Setting up the frontend",id:"setting-up-the-frontend",level:2},{value:"Adding your GM portal chain to the config",id:"adding-your-gm-portal-chain-to-the-config",level:2}],c={toc:p};function d(e){let{components:n,...r}=e;return(0,o.kt)("wrapper",(0,a.Z)({},c,r,{components:n,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"gm-world-frontend-tutorial"},"GM world frontend tutorial"),(0,o.kt)("p",null,"In this tutorial, we'll learn how to use ",(0,o.kt)("a",{parentName:"p",href:"https://cosmology.tech/"},"Cosmology")," to\ncreate a frontend for our ",(0,o.kt)("a",{parentName:"p",href:"../gm-world"},"GM world")," rollup."),(0,o.kt)("p",null,"Cosmology enables developers to build web3 apps in the Interchain Ecosystem.\nWith Cosmology, it's simple to begin building apps that communicate with\nCosmos SDK and CosmWasm chains."),(0,o.kt)("p",null,"We'll be using ",(0,o.kt)("inlineCode",{parentName:"p"},"create-cosmos-app")," in this tutorial to scaffold\na frontend and add the chain information for our rollup."),(0,o.kt)("p",null,"In the end, you'll have something that looks like this\n",(0,o.kt)("a",{parentName:"p",href:"https://rollkit-frontend.vercel.app"},"demo"),"\n(",(0,o.kt)("a",{parentName:"p",href:"https://github.com/jcstein/rollkit-frontend"},"repo"),")."),(0,o.kt)("h2",{id:"getting-started"},"Getting started"),(0,o.kt)("p",null,"In order to complete this tutorial you will need to have completed\nthe ",(0,o.kt)("a",{parentName:"p",href:"../gm-world"},"GM world tutorial"),". This requires a running rollup\non your local machine."),(0,o.kt)("h2",{id:"setting-up-the-frontend"},"Setting up the frontend"),(0,o.kt)("p",null,"Now that you have your rollup running, you are ready to scaffold\nthe frontend! In your terminal, first install ",(0,o.kt)("inlineCode",{parentName:"p"},"create-cosmos-app"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"npm install -g create-cosmos-app\n")),(0,o.kt)("p",null,"Now scaffold an app:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"create-cosmos-app\n")),(0,o.kt)("p",null,"In this tutorial, we're using the following setting and your output\nwill look similar to this if everything is successful:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"? [name] Enter your new app name gm-world\nCloning into 'gm-world'...\n? [template] which template connect-multi-chain\nyarn install v1.22.19\n[1/4] Resolving packages...\n[2/4] Fetching packages...\n[3/4] Linking dependencies...\n[4/4] Building fresh packages...\nsuccess Saved lockfile.\nDone in 42.23s.\n\n\n | _ _\n === |.===. '\\-//`\n (o o) {}o o{} (o o)\nooO--(_)--Ooo-ooO--(_)--Ooo-ooO--(_)--Ooo-\n\n\u2728 Have fun! Now you can start on your project \u269b\ufe0f\n\nNow, run this command:\n\ncd ./gm-world && yarn dev\n")),(0,o.kt)("p",null,"Follow the instructions at the end of the output to start your app:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd ./gm-world && yarn dev\n")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"cca-3.png",src:t(259).Z,width:"3324",height:"1980"})),(0,o.kt)("h2",{id:"adding-your-gm-portal-chain-to-the-config"},"Adding your GM portal chain to the config"),(0,o.kt)("p",null,"First, we'll need to make some changes with the default config."),(0,o.kt)("p",null,"We need to add the array of chains that we would like to test\nin the ",(0,o.kt)("inlineCode",{parentName:"p"},"components/wallet.tsx")," file on underneath imports:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},"const allowedChains = [\n 'gmrollup',\n 'celestiatestnet',\n 'celestiatestnet2',\n 'celestiatestnet3',\n];\n")),(0,o.kt)("p",null,"In ",(0,o.kt)("inlineCode",{parentName:"p"},"chainOptions")," change ",(0,o.kt)("inlineCode",{parentName:"p"},"chainRecords")," this to show only the allowed chains\nfrom your array:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx",metastring:'title="hi"',title:'"hi"'},"chainRecords\n .filter((chainRecord) => allowedChains.includes(chainRecord.name))\n .map((chainRecord) => {\n")),(0,o.kt)("p",null,"In ",(0,o.kt)("inlineCode",{parentName:"p"},"configs/defaults.ts")," change ",(0,o.kt)("inlineCode",{parentName:"p"},"defaultChainName")," to:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},"export const defaultChainName = 'gmrollup';\n")),(0,o.kt)("p",null,"Now you're ready to see only the chains you've selected, but first, we need\nto set up the config for ",(0,o.kt)("inlineCode",{parentName:"p"},"gmrollup"),"!"),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"config")," directory, create a new file called ",(0,o.kt)("inlineCode",{parentName:"p"},"chain.ts"),". This will\nbe your config for your GM rollup."),(0,o.kt)("p",null,"In that file, put the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},'export const chain = {\n "$schema": "../../chain.schema.json",\n "chain_name": "gmrollup",\n "chain_id": "gm",\n "pretty_name": "my gm rollup",\n "status": "live",\n "network_type": "testnet",\n "bech32_prefix": "gm",\n "daemon_name": "gmd",\n "node_home": "$HOME/.gm",\n "key_algos": [\n "secp256k1"\n ],\n "slip44": 118,\n "fees": {\n "fee_tokens": [\n {\n "denom": "ustake",\n "fixed_min_gas_price": 0\n }\n ]\n },\n "apis": {\n "rpc": [\n {\n "address": "http://localhost:26657",\n "provider": "JCS"\n }\n ],\n "rest": [\n {\n "address": "http://localhost:1317",\n "provider": "JCS"\n }\n ]\n },\n "beta": true,\n }\n')),(0,o.kt)("p",null,"Create a new file in ",(0,o.kt)("inlineCode",{parentName:"p"},"config")," called ",(0,o.kt)("inlineCode",{parentName:"p"},"assetlist.ts")," and add the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},'export const assetlist = {\n "$schema": "../../assetlist.schema.json",\n "chain_name": "gmrollup",\n "assets": [\n {\n "description": "",\n "denom_units": [\n {\n "denom": "ustake",\n "exponent": 0\n },\n {\n "denom": "stake",\n "exponent": 6\n }\n ],\n "base": "stake",\n "name": "GM rollup",\n "display": "stake",\n "symbol": "STAKE",\n "logo_URIs": {\n "svg": "https://raw.githubusercontent.com/jcstein/gm-portal/b030ce3fe548d188fbacb6b932d7e51dc7afd65e/frontend/public/gm.svg"\n }\n }\n ]\n }\n')),(0,o.kt)("p",null,"Create a new file in ",(0,o.kt)("inlineCode",{parentName:"p"},"config")," directory called ",(0,o.kt)("inlineCode",{parentName:"p"},"defaults.ts"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},"import { assets } from 'chain-registry';\nimport { AssetList, Asset } from '@chain-registry/types';\n\nexport const defaultChainName = 'gmrollup';\n\nexport const getChainAssets = (chainName: string = defaultChainName) => {\n return assets.find((chain) => chain.chain_name === chainName) as AssetList;\n};\n\nexport const getCoin = (chainName: string = defaultChainName) => {\n const chainAssets = getChainAssets(chainName);\n return chainAssets.assets[0] as Asset;\n};\n")),(0,o.kt)("p",null,"In ",(0,o.kt)("inlineCode",{parentName:"p"},"_app.tsx")," you can now import ",(0,o.kt)("inlineCode",{parentName:"p"},"assetlist")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"chain")," with your\nnew GM config!"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},'# other imports\nimport { chain } from "../config/chain"\nimport { assetlist } from "../config/assetlist"\n\n# rest of code\n')),(0,o.kt)("p",null,"Then, modify your ",(0,o.kt)("inlineCode",{parentName:"p"},"ChainProvider"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},"\n")),(0,o.kt)("p",null,"You may notice that we added:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-tsx"},"endpointOptions={{isLazy: true}}\n")),(0,o.kt)("p",null,"This will save our localhost RPC from being overridden."),(0,o.kt)("p",null,"Congratulations! You now have a frontend for your rollup.\nWhat features do you want to add now?"),(0,o.kt)("p",null,"You may notice that the icons for Celestia testnets are not loading,\nthis is due to an outdated version of the chain registry."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"cca.png",src:t(4812).Z,width:"1196",height:"1102"})),(0,o.kt)("p",null,"To update\nthese, you can use your terminal:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd $HOME && cd gm-world\nyarn upgrade-interactive --latest\n")),(0,o.kt)("p",null,"Select ",(0,o.kt)("inlineCode",{parentName:"p"},"@chain-registry/types")," by using arrow keys and the spacebar\nto select it. Do the same with ",(0,o.kt)("inlineCode",{parentName:"p"},"@cosmos-kit/core"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"@cosmos-kit\ncosmostation"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"@cosmos-kit/keplr"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"@cosmos-kit/leap"),",\n",(0,o.kt)("inlineCode",{parentName:"p"},"@cosmos-kit/react"),", ",(0,o.kt)("inlineCode",{parentName:"p"},"@chain-registry/cosmostation")," and\n",(0,o.kt)("inlineCode",{parentName:"p"},"chain-registry"),"."),(0,o.kt)("p",null,"Now use enter to upgrade the dependencies!"),(0,o.kt)("p",null,"Head back to your frontend and take a look, you should see the\nupdated icons."),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"cca-2.png",src:t(2673).Z,width:"806",height:"644"})))}d.isMDXComponent=!0},2673:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/cca-2-d77b4e415ca0aa4499d267071d403858.png"},259:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/cca-3-11f96a3e7bbe5bc5755442e00d10040e.png"},4812:(e,n,t)=>{t.d(n,{Z:()=>a});const a=t.p+"assets/images/cca-54747f2736cbb93d7f0c2b52582dbb5b.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/2e006f0d.d207a387.js b/pr-preview/pr-192/assets/js/2e006f0d.d207a387.js deleted file mode 100644 index 2e1bd2751..000000000 --- a/pr-preview/pr-192/assets/js/2e006f0d.d207a387.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1392],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var o=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function n(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,o)}return r}function l(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=o.createContext({}),u=function(e){var t=o.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=u(e.components);return o.createElement(i.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var r=e.components,a=e.mdxType,n=e.originalType,i=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=u(r),h=a,m=c["".concat(i,".").concat(h)]||c[h]||d[h]||n;return r?o.createElement(m,l(l({ref:t},p),{},{components:r})):o.createElement(m,l({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var n=r.length,l=new Array(n);l[0]=h;var s={};for(var i in t)hasOwnProperty.call(t,i)&&(s[i]=t[i]);s.originalType=e,s[c]="string"==typeof e?e:a,l[1]=s;for(var u=2;u{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>c,frontMatter:()=>n,metadata:()=>s,toc:()=>u});var o=r(7462),a=(r(7294),r(3905));const n={sidebar_label:"How to restart your rollup",description:"Restart your Rollkit rollup safely"},l="\ud83d\udd04 How to restart your rollup",s={unversionedId:"tutorials/restart-rollkit-rollup",id:"tutorials/restart-rollkit-rollup",title:"\ud83d\udd04 How to restart your rollup",description:"Restart your Rollkit rollup safely",source:"@site/docs/tutorials/restart-rollkit-rollup.md",sourceDirName:"tutorials",slug:"/tutorials/restart-rollkit-rollup",permalink:"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/restart-rollkit-rollup.md",tags:[],version:"current",frontMatter:{sidebar_label:"How to restart your rollup",description:"Restart your Rollkit rollup safely"},sidebar:"docs",previous:{title:"Recipe book tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/recipe-book"},next:{title:"Intermediate",permalink:"/pr-preview/pr-192/docs/category/intermediate"}},i={},u=[{value:"\ud83d\udcbb Setup of this example",id:"-setup-of-this-example",level:2},{value:"\ud83d\udfe0 Errors in this example",id:"-errors-in-this-example",level:3},{value:"\ud83d\udcb0 Re-fund your account",id:"-re-fund-your-account",level:2},{value:"\ud83d\uded1 Stopping your rollup",id:"-stopping-your-rollup",level:2},{value:"\ud83d\udd01 Restarting your rollup",id:"-restarting-your-rollup",level:2},{value:"\u26fd Increase the gas fee",id:"-increase-the-gas-fee",level:3},{value:"\ud83d\udee2\ufe0f Reduce gas fee & restart again",id:"\ufe0f-reduce-gas-fee--restart-again",level:3}],p={toc:u};function c(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,o.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"-how-to-restart-your-rollup"},"\ud83d\udd04 How to restart your rollup"),(0,a.kt)("p",null,"This guide will teach you how to restart your Rollkit rollup in the case that the node that you are using to post blocks to your DA and consensus layer runs out of funds (tokens)."),(0,a.kt)("h2",{id:"-setup-of-this-example"},"\ud83d\udcbb Setup of this example"),(0,a.kt)("p",null,"In this example, we're using Celestia's ",(0,a.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race/"},"Blockspacerace testnet")," and running an ",(0,a.kt)("a",{parentName:"p",href:"/pr-preview/pr-192/docs/tutorials/ethermint"},"Ethermint")," chain. In this example, our Celestia DA light node ran out of Blockspace Race TIA and we are unable to post new blocks to Celestia due to a ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/cosmos/cosmos-sdk/blob/main/types/errors/errors.go#L95"},(0,a.kt)("inlineCode",{parentName:"a"},"Code: 19"))," error. This error is defined by Cosmos SDK as:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-go"},'// ErrTxInMempoolCache defines an ABCI typed error where a tx already exists in the mempool.\nErrTxInMempoolCache = Register(RootCodespace, 19, "tx already in mempool")\n')),(0,a.kt)("p",null,"In order to get around this error, and the same error on other Rollkit rollups, you will need to re-fund your Celestia account and increase the gas fee. This will override the transaction that is stuck in the mempool."),(0,a.kt)("p",null,"If you top up the balance of your node and don't increase the gas fee, you will still encounter the ",(0,a.kt)("inlineCode",{parentName:"p"},"Code: 19")," error because there is a transaction (posting block to DA) that is duplicate to one that already exists. In order to get around this, you'll need to increase the gas fee and restart the chain."),(0,a.kt)("h3",{id:"-errors-in-this-example"},"\ud83d\udfe0 Errors in this example"),(0,a.kt)("p",null,"This is what the errors will look like if your DA node runs out of funding or you restart the chain without changing the gas fee:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"4:51PM INF submitting block to DA layer height=28126 module=BlockManager\n4:51PM ERR DA layer submission failed error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=1 module=BlockManager\n4:51PM ERR DA layer submission failed Error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=2 module=BlockManager\n4:51PM ERR DA layer submission failed error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=3 module=BlockManager\n4:51PM ERR DA layer submission failed error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=4 module=BlockManager\n4:51PM ERR DA layer submission failed error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=5 module=BlockManager\n4:51PM ERR DA layer submission failed error=\"Codespace: 'sdk', Code: 19, Message: \" attempt=6 module=BlockManager\n")),(0,a.kt)("h2",{id:"-re-fund-your-account"},"\ud83d\udcb0 Re-fund your account"),(0,a.kt)("p",null,"First, you'll need to send more tokens to the account running your Celestia node. If you didn't keep track of your key, you can run the following to get your address:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"cd $HOME && cd celestia-node\n./cel-key list --keyring-backend test --node.type light --p2p.network \n")),(0,a.kt)("h2",{id:"-stopping-your-rollup"},"\ud83d\uded1 Stopping your rollup"),(0,a.kt)("p",null,"You can stop your Ethermint chain (or other Rollkit rollup) by using ",(0,a.kt)("inlineCode",{parentName:"p"},"Control + C")," in your terminal where the node is running."),(0,a.kt)("h2",{id:"-restarting-your-rollup"},"\ud83d\udd01 Restarting your rollup"),(0,a.kt)("p",null,"First, be sure that you are using the same Namespace ID as you were before your Celestia node ran out of tokens."),(0,a.kt)("p",null,"Next, you'll need to fetch the current block height and set the variable accordingly for your start command. In this example, we're using ",(0,a.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspace Race testnet")," on Celestia for DA and consensus:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"DA_BLOCK_HEIGHT=$(curl https://rpc-blockspacerace.pops.one/block | jq -r '.result.block.header.height')\n")),(0,a.kt)("h3",{id:"-increase-the-gas-fee"},"\u26fd Increase the gas fee"),(0,a.kt)("p",null,"To reiterate, before restarting the chain, you will need to increase the gas fee in order to avoid a ",(0,a.kt)("inlineCode",{parentName:"p"},"Code: 19")," error:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config=\'{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6900}\' --rollkit.namespace_id 8BE3175CBF305BC2 --rollkit.da_start_height $DA_BLOCK_HEIGHT\n')),(0,a.kt)("h3",{id:"\ufe0f-reduce-gas-fee--restart-again"},"\ud83d\udee2\ufe0f Reduce gas fee & restart again"),(0,a.kt)("p",null,"In order to save your TIA, we also recommend stopping the chain with ",(0,a.kt)("inlineCode",{parentName:"p"},"Control + C"),", changing the gas fee back to the default (in our case, 6000 utia), fetching current block height, and restarting the chain:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config=\'{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6000}\' --rollkit.namespace_id 8BE3175CBF305BC2 --rollkit.da_start_height $DA_BLOCK_HEIGHT\n')),(0,a.kt)("p",null,"\ud83c\udf8a Congrats! You've successfully restarted your Rollkit rollup after running out of TIA."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/32f16e92.0783d6a4.js b/pr-preview/pr-192/assets/js/32f16e92.0783d6a4.js deleted file mode 100644 index ceb3c24da..000000000 --- a/pr-preview/pr-192/assets/js/32f16e92.0783d6a4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8757],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>d});var l=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function i(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,l)}return o}function r(e){for(var t=1;t=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var s=l.createContext({}),c=function(e){var t=l.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},u=function(e){var t=c(e.components);return l.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var o=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),p=c(o),h=n,d=p["".concat(s,".").concat(h)]||p[h]||m[h]||i;return o?l.createElement(d,r(r({ref:t},u),{},{components:o})):l.createElement(d,r({ref:t},u))}));function d(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=o.length,r=new Array(i);r[0]=h;var a={};for(var s in t)hasOwnProperty.call(t,s)&&(a[s]=t[s]);a.originalType=e,a[p]="string"==typeof e?e:n,r[1]=a;for(var c=2;c{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var l=o(7462),n=(o(7294),o(3905));const i={slug:"lets-roll-community-call",title:"Let's Roll - Rollkit's community call",authors:["AlCJoseph"],tags:["Rollkit"],description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."},r=void 0,a={permalink:"/pr-preview/pr-192/blog/lets-roll-community-call",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-03-08-lets-roll.mdx",source:"@site/blog/2023-03-08-lets-roll.mdx",title:"Let's Roll - Rollkit's community call",description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.",date:"2023-03-08T00:00:00.000Z",formattedDate:"March 8, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"}],readingTime:3.245,hasTruncateMarker:!1,authors:[{name:"Joseph Al-Chami",url:"https://github.com/AlCJoseph",imageURL:"https://github.com/AlCJoseph.png",key:"AlCJoseph"}],frontMatter:{slug:"lets-roll-community-call",title:"Let's Roll - Rollkit's community call",authors:["AlCJoseph"],tags:["Rollkit"],description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."},nextItem:{title:"Sovereign rollups on Bitcoin with Rollkit",permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},s={authorsImageUrls:[void 0]},c=[{value:"TL;DR",id:"tldr",level:2},{value:"Just merge it",id:"just-merge-it",level:2},{value:"What is Let\u2019s Roll?",id:"what-is-lets-roll",level:2},{value:"Conclusion",id:"conclusion",level:2}],u={toc:c};function p(e){let{components:t,...i}=e;return(0,n.kt)("wrapper",(0,l.Z)({},u,i,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Rollkit blog cover",src:o(5756).Z,width:"3000",height:"1500"})),(0,n.kt)("p",null,"Last Sunday, we released the first ",(0,n.kt)("a",{parentName:"p",href:"https://rollkit.dev/blog/sovereign-rollups-on-bitcoin/"},"research implementation")," that allows Rollkit rollups to use Bitcoin for data availability. "),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://twitter.com/RollkitDev/status/1632438374513676288"},"This announcement")," has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They\u2019re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements."),(0,n.kt)("p",null,"We believe that there\u2019s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks."),(0,n.kt)("p",null,"That\u2019s why we\u2019re happy to announce that we\u2019re launching a Rollkit\u2019s community call: Let\u2019s Roll."),(0,n.kt)("h2",{id:"tldr"},"TL;DR"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Rollkit is launching its community call, Let\u2019s Roll. You can subscribe to the community calendar ",(0,n.kt)("a",{parentName:"p",href:"https://calendar.google.com/calendar/u/0/embed?src=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com&ctz=America/Toronto"},"here"))),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The first meeting is scheduled on ",(0,n.kt)("a",{parentName:"p",href:"https://us06web.zoom.us/j/83308619122"},"Zoom")," for March 21, 2023, 6pm CET(12pm EST, 9am PST).")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Builders using Rollkit can now present their projects at Let\u2019s Roll. Reach out to us on ",(0,n.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram")," "))),(0,n.kt)("h2",{id:"just-merge-it"},"Just merge it"),(0,n.kt)("p",null,"Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good. "),(0,n.kt)("p",null,"However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit\u2019s development."),(0,n.kt)("p",null,"By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community. "),(0,n.kt)("p",null,"One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use."),(0,n.kt)("p",null,"Our promise, as core contributors, is to do our best to make \u201cjust merge it\u201d a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated. "),(0,n.kt)("p",null,"That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."),(0,n.kt)("h2",{id:"what-is-lets-roll"},"What is Let\u2019s Roll?"),(0,n.kt)("p",null,"Let's Roll is a dynamic community-focused meeting that brings together all Rollkit\u2019s contributors to drive the innovation and development of Rollkit."),(0,n.kt)("p",null,"This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects."),(0,n.kt)("p",null,"Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently."),(0,n.kt)("p",null,"The meeting will be hosted on ",(0,n.kt)("a",{parentName:"p",href:"https://us06web.zoom.us/j/83308619122"},"Zoom"),". Subscribe to the following ",(0,n.kt)("a",{parentName:"p",href:"https://calendar.google.com/calendar/u/0/r?cid=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com"},"Google calendar")," so that you can be notified of future community calls."),(0,n.kt)("h2",{id:"conclusion"},"Conclusion"),(0,n.kt)("p",null,"Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework.\nWith demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project."),(0,n.kt)("p",null,"We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together."),(0,n.kt)("p",null,"So, join us, roll with us, and let's shape the future of rollup frameworks together."))}p.isMDXComponent=!0},5756:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/lets-roll-a8b580bec3f0ea690483252f65daa0c1.jpg"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/33efe628.2b1da1df.js b/pr-preview/pr-192/assets/js/33efe628.2b1da1df.js deleted file mode 100644 index fb538880f..000000000 --- a/pr-preview/pr-192/assets/js/33efe628.2b1da1df.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6688],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>m});var l=o(7294);function i(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function a(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,l)}return o}function r(e){for(var t=1;t=0||(i[o]=e[o]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(l=0;l=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(i[o]=e[o])}return i}var s=l.createContext({}),p=function(e){var t=l.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},u=function(e){var t=p(e.components);return l.createElement(s.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var o=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=n(e,["components","mdxType","originalType","parentName"]),c=p(o),h=i,m=c["".concat(s,".").concat(h)]||c[h]||d[h]||a;return o?l.createElement(m,r(r({ref:t},u),{},{components:o})):l.createElement(m,r({ref:t},u))}));function m(e,t){var o=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=o.length,r=new Array(a);r[0]=h;var n={};for(var s in t)hasOwnProperty.call(t,s)&&(n[s]=t[s]);n.originalType=e,n[c]="string"==typeof e?e:i,r[1]=n;for(var p=2;p{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>c,frontMatter:()=>a,metadata:()=>n,toc:()=>p});var l=o(7462),i=(o(7294),o(3905));const a={slug:"introducing-rollkit",title:"Introducing Rollkit: a modular rollup framework",authors:["AlCJoseph","alex-beckett"],tags:["Rollkit","Celestia"],description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation"},r=void 0,n={permalink:"/pr-preview/pr-192/blog/introducing-rollkit",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-02-21-introducing-rollkit.mdx",source:"@site/blog/2023-02-21-introducing-rollkit.mdx",title:"Introducing Rollkit: a modular rollup framework",description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation",date:"2023-02-21T00:00:00.000Z",formattedDate:"February 21, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"},{label:"Celestia",permalink:"/pr-preview/pr-192/blog/tags/celestia"}],readingTime:5.985,hasTruncateMarker:!1,authors:[{name:"Joseph Al-Chami",url:"https://github.com/AlCJoseph",imageURL:"https://github.com/AlCJoseph.png",key:"AlCJoseph"},{name:"Alex Beckett",url:"https://github.com/alex-beckett",imageURL:"https://github.com/alex-beckett.png",key:"alex-beckett"}],frontMatter:{slug:"introducing-rollkit",title:"Introducing Rollkit: a modular rollup framework",authors:["AlCJoseph","alex-beckett"],tags:["Rollkit","Celestia"],description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation"},prevItem:{title:"Sovereign rollups on Bitcoin with Rollkit",permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},s={authorsImageUrls:[void 0,void 0]},p=[{value:"Tl;dr:",id:"tldr",level:2},{value:"Deploying a new chain is hard",id:"deploying-a-new-chain-is-hard",level:2},{value:"Freedom to deploy",id:"freedom-to-deploy",level:2},{value:"Vision for Rollkit",id:"vision-for-rollkit",level:2},{value:"Execution environments",id:"execution-environments",level:3},{value:"Sequencers",id:"sequencers",level:3},{value:"Proof schemes",id:"proof-schemes",level:3},{value:"Rollup types",id:"rollup-types",level:3},{value:"Rollkit is neutral",id:"rollkit-is-neutral",level:2},{value:"Next steps",id:"next-steps",level:2}],u={toc:p};function c(e){let{components:t,...a}=e;return(0,i.kt)("wrapper",(0,l.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"The original version of this blog post can be found on the ",(0,i.kt)("a",{parentName:"em",href:"https://blog.celestia.org/introducing-rollkit-a-modular-rollup-framework/"},"Celestia blog"),".")),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit blog cover",src:o(6197).Z,width:"3000",height:"1500"})),(0,i.kt)("p",null,"Today, we\u2019re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation."),(0,i.kt)("p",null,"Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/informalsystems/tendermint/tree/main/abci"},"ABCI"),"-compatible blockchain app, including Cosmos chains."),(0,i.kt)("p",null,"In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at ",(0,i.kt)("a",{parentName:"p",href:"/"},"rollkit.dev"),"."),(0,i.kt)("h2",{id:"tldr"},"Tl;dr:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"You can now ",(0,i.kt)("a",{parentName:"li",href:"/"},"build with Rollkit")," on Celestia\u2019s Mocha testnet. Check out the ",(0,i.kt)("a",{parentName:"li",href:"/"},"docs")),(0,i.kt)("li",{parentName:"ul"},"You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit\u2019s modular framework"),(0,i.kt)("li",{parentName:"ul"},"Join our Rollkit developer calls that begin in April to help guide its development")),(0,i.kt)("h2",{id:"deploying-a-new-chain-is-hard"},"Deploying a new chain is hard"),(0,i.kt)("p",null,"Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility."),(0,i.kt)("p",null,"For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs."),(0,i.kt)("p",null,"In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could."),(0,i.kt)("h2",{id:"freedom-to-deploy"},"Freedom to deploy"),(0,i.kt)("p",null,"Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain."),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit comparison table",src:o(3988).Z,width:"1600",height:"374"})),(0,i.kt)("p",null,"Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain."),(0,i.kt)("p",null,"With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don\u2019t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers."),(0,i.kt)("h2",{id:"vision-for-rollkit"},"Vision for Rollkit"),(0,i.kt)("p",null,"In the spirit of modularity, Rollkit\u2019s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit."),(0,i.kt)("p",null,"In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit\u2019s customizable stack will enable developers to bring their products to market faster and with more flexibility."),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit lego image",src:o(6194).Z,width:"1600",height:"1322"})),(0,i.kt)("h3",{id:"execution-environments"},"Execution environments"),(0,i.kt)("p",null,"Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch."),(0,i.kt)("h3",{id:"sequencers"},"Sequencers"),(0,i.kt)("p",null,"Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers."),(0,i.kt)("h3",{id:"proof-schemes"},"Proof schemes"),(0,i.kt)("p",null,"Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs."),(0,i.kt)("h3",{id:"rollup-types"},"Rollup types"),(0,i.kt)("p",null,"Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups."),(0,i.kt)("p",null,"Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its ",(0,i.kt)("a",{parentName:"p",href:"/docs/rollkit-stack"},"current state"),", Rollkit rollups are ",(0,i.kt)("a",{parentName:"p",href:"https://blog.celestia.org/sovereign-rollup-chains"},"sovereign rollups")," with single sequencers, with support for a pessimistic mode and a ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/manav/state_fraud_proofs_adr/docs/lazy-adr/adr-009-state-fraud-proofs.md"},"work-in-progress optimistic mode"),". ",(0,i.kt)("a",{parentName:"p",href:"/docs/category/tutorials"},"Integration tutorials")," are ready and available with Cosmos SDK, Ethermint, and CosmWasm."),(0,i.kt)("p",null,"We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action. "),(0,i.kt)("h2",{id:"rollkit-is-neutral"},"Rollkit is neutral"),(0,i.kt)("p",null,"Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract."),(0,i.kt)("p",null,"Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/EclipseFND"},"Eclipse")," (Solana VM rollups), ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/dymensionXYZ"},"Dymension")," (settled Cosmos rollups), ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/sovereign_labs"},"Sovereign Labs")," (sovereign ZK rollups), and ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/optimismFND"},"Optimism")," (EVM rollups)."),(0,i.kt)("p",null,"To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site."),(0,i.kt)("p",null,"This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/567b9f500db8055289365ea63450cefe4b135077/da/da.go#L60"},"data availability interface"),"."),(0,i.kt)("p",null,"The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it."),(0,i.kt)("p",null,"Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack."),(0,i.kt)("p",null,"We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it\u2019s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up."),(0,i.kt)("h2",{id:"next-steps"},"Next steps"),(0,i.kt)("p",null,"Moving towards a community-led project means increased visibility, transparency and inclusivity. That\u2019s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit. "),(0,i.kt)("p",null,"Learn more about how Rollkit works ",(0,i.kt)("a",{parentName:"p",href:"/"},"on the new Rollkit website")," (you're already on it!). And don\u2019t forget to check out the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit"},"Rollkit repo")," too."),(0,i.kt)("p",null,"Let\u2019s build modular together."))}c.isMDXComponent=!0},3988:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/comparison-table-7c865eb80a6add486978246e68eb69fa.png"},6197:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/rollkit-blog-cover-8cba9a7759f1f728fb99c4bb344ef12b.png"},6194:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/rollkit-lego-67992ef3767eb2c35eff95a0240749bd.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/4650ee82.3692f0e3.js b/pr-preview/pr-192/assets/js/4650ee82.3692f0e3.js deleted file mode 100644 index 20e063b28..000000000 --- a/pr-preview/pr-192/assets/js/4650ee82.3692f0e3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7238],{1007:e=>{e.exports=JSON.parse('[{"label":"Rollkit","permalink":"/pr-preview/pr-192/blog/tags/rollkit","count":3},{"label":"Bitcoin","permalink":"/pr-preview/pr-192/blog/tags/bitcoin","count":1},{"label":"Celestia","permalink":"/pr-preview/pr-192/blog/tags/celestia","count":1}]')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/4789b10c.db037f9d.js b/pr-preview/pr-192/assets/js/4789b10c.db037f9d.js deleted file mode 100644 index 233093224..000000000 --- a/pr-preview/pr-192/assets/js/4789b10c.db037f9d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3553],{247:e=>{e.exports=JSON.parse('{"title":"Advanced","slug":"/category/advanced","permalink":"/pr-preview/pr-192/docs/category/advanced","navigation":{"previous":{"title":"CosmWasm tutorial","permalink":"/pr-preview/pr-192/docs/tutorials/cosmwasm"},"next":{"title":"Ethermint (EVM) tutorial","permalink":"/pr-preview/pr-192/docs/tutorials/ethermint"}}}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/48bdfc14.09373ca8.js b/pr-preview/pr-192/assets/js/48bdfc14.09373ca8.js deleted file mode 100644 index ec6e09f10..000000000 --- a/pr-preview/pr-192/assets/js/48bdfc14.09373ca8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7819],{5409:e=>{e.exports=JSON.parse('{"title":"Tutorials","slug":"/category/tutorials","permalink":"/pr-preview/pr-192/docs/category/tutorials","navigation":{"previous":{"title":"Transaction flow","permalink":"/pr-preview/pr-192/docs/transaction-flow"},"next":{"title":"Beginner","permalink":"/pr-preview/pr-192/docs/category/beginner"}}}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/4972.4136cbbb.js b/pr-preview/pr-192/assets/js/4972.4136cbbb.js deleted file mode 100644 index 23579b4ed..000000000 --- a/pr-preview/pr-192/assets/js/4972.4136cbbb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4972],{4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>c});var a=n(7294),l=n(5999),o=n(1944),r=n(7676);function c(){return a.createElement(a.Fragment,null,a.createElement(o.d,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/53f25740.92622228.js b/pr-preview/pr-192/assets/js/53f25740.92622228.js deleted file mode 100644 index f2bbee8cc..000000000 --- a/pr-preview/pr-192/assets/js/53f25740.92622228.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9048],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>g});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function r(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},u=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},m="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,l=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=p(n),d=o,g=m["".concat(s,".").concat(d)]||m[d]||c[d]||l;return n?a.createElement(g,r(r({ref:t},u),{},{components:n})):a.createElement(g,r({ref:t},u))}));function g(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=n.length,r=new Array(l);r[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[m]="string"==typeof e?e:o,r[1]=i;for(var p=2;p{n.d(t,{Z:()=>r});var a=n(7294),o=n(6010);const l="tabItem_Ymn6";function r(e){let{children:t,hidden:n,className:r}=e;return a.createElement("div",{role:"tabpanel",className:(0,o.Z)(l,r),hidden:n},t)}},5488:(e,t,n)=>{n.d(t,{Z:()=>d});var a=n(7462),o=n(7294),l=n(6010),r=n(2389),i=n(7392),s=n(7094),p=n(2466);const u="tabList__CuJ",m="tabItem_LNqP";function c(e){const{lazy:t,block:n,defaultValue:r,values:c,groupId:d,className:g}=e,h=o.Children.map(e.children,(e=>{if((0,o.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)})),k=c??h.map((e=>{let{props:{value:t,label:n,attributes:a}}=e;return{value:t,label:n,attributes:a}})),y=(0,i.l)(k,((e,t)=>e.value===t.value));if(y.length>0)throw new Error(`Docusaurus error: Duplicate values "${y.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`);const f=null===r?r:r??h.find((e=>e.props.default))?.props.value??h[0].props.value;if(null!==f&&!k.some((e=>e.value===f)))throw new Error(`Docusaurus error: The has a defaultValue "${f}" but none of its children has the corresponding value. Available values are: ${k.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);const{tabGroupChoices:N,setTabGroupChoices:b}=(0,s.U)(),[v,w]=(0,o.useState)(f),C=[],{blockElementScrollPositionUntilNextRender:T}=(0,p.o5)();if(null!=d){const e=N[d];null!=e&&e!==v&&k.some((t=>t.value===e))&&w(e)}const I=e=>{const t=e.currentTarget,n=C.indexOf(t),a=k[n].value;a!==v&&(T(t),w(a),null!=d&&b(d,String(a)))},x=e=>{let t=null;switch(e.key){case"Enter":I(e);break;case"ArrowRight":{const n=C.indexOf(e.currentTarget)+1;t=C[n]??C[0];break}case"ArrowLeft":{const n=C.indexOf(e.currentTarget)-1;t=C[n]??C[C.length-1];break}}t?.focus()};return o.createElement("div",{className:(0,l.Z)("tabs-container",u)},o.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,l.Z)("tabs",{"tabs--block":n},g)},k.map((e=>{let{value:t,label:n,attributes:r}=e;return o.createElement("li",(0,a.Z)({role:"tab",tabIndex:v===t?0:-1,"aria-selected":v===t,key:t,ref:e=>C.push(e),onKeyDown:x,onClick:I},r,{className:(0,l.Z)("tabs__item",m,r?.className,{"tabs__item--active":v===t})}),n??t)}))),t?(0,o.cloneElement)(h.filter((e=>e.props.value===v))[0],{className:"margin-top--md"}):o.createElement("div",{className:"margin-top--md"},h.map(((e,t)=>(0,o.cloneElement)(e,{key:t,hidden:e.props.value!==v})))))}function d(e){const t=(0,r.Z)();return o.createElement(c,(0,a.Z)({key:String(t)},e))}},651:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>s,default:()=>d,frontMatter:()=>i,metadata:()=>p,toc:()=>m});var a=n(7462),o=(n(7294),n(3905)),l=n(5488),r=n(5162);const i={sidebar_label:"GM world tutorial",description:"Build a sovereign rollup with Ignite CLI, Celestia and Rollkit locally and on a testnet"},s="GM world rollup",p={unversionedId:"tutorials/gm-world",id:"tutorials/gm-world",title:"GM world rollup",description:"Build a sovereign rollup with Ignite CLI, Celestia and Rollkit locally and on a testnet",source:"@site/docs/tutorials/gm-world.md",sourceDirName:"tutorials",slug:"/tutorials/gm-world",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/gm-world.md",tags:[],version:"current",frontMatter:{sidebar_label:"GM world tutorial",description:"Build a sovereign rollup with Ignite CLI, Celestia and Rollkit locally and on a testnet"},sidebar:"docs",previous:{title:"Building & deploying a rollup",permalink:"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup"},next:{title:"GM world frontend tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world-frontend"}},u={},m=[{value:"\u2600\ufe0f Introduction",id:"\ufe0f-introduction",level:2},{value:"\ud83e\udd14 What is GM?",id:"-what-is-gm",level:2},{value:"Dependencies",id:"dependencies",level:2},{value:"\ud83c\udfc3\xa0Install Golang on Linux",id:"install-golang-on-linux",level:4},{value:"\ud83d\udd25\xa0Install Ignite CLI on Linux",id:"install-ignite-cli-on-linux",level:4},{value:"\ud83c\udfc3\xa0Install Golang on macOS",id:"install-golang-on-macos",level:4},{value:"\ud83d\udd25\xa0Install Ignite CLI on macOS",id:"install-ignite-cli-on-macos",level:4},{value:"\ud83c\udf7a\xa0Install Homebrew on macOS",id:"install-homebrew-on-macos",level:4},{value:"\ud83c\udfc3\xa0Install wget and jq on macOS",id:"install-wget-and-jq-on-macos",level:4},{value:"Part one",id:"part-one",level:2},{value:"\ud83d\udcbb Prerequisites",id:"-prerequisites",level:3},{value:"\ud83c\udfe0 Running local devnet with a Rollkit rollup",id:"-running-local-devnet-with-a-rollkit-rollup",level:3},{value:"\ud83d\udd0e Query your balance",id:"-query-your-balance",level:3},{value:"\ud83d\udfe2 Start, stop, or remove your container",id:"-start-stop-or-remove-your-container",level:3},{value:"\ud83c\udfd7\ufe0f Building your sovereign rollup",id:"\ufe0f-building-your-sovereign-rollup",level:3},{value:"\ud83d\uddde\ufe0f Install Rollkit",id:"\ufe0f-install-rollkit",level:3},{value:"\u25b6\ufe0f Start your rollup",id:"\ufe0f-start-your-rollup",level:3},{value:"\ud83d\udd11 Keys",id:"-keys",level:4},{value:"\ud83d\udcb8 Transactions",id:"-transactions",level:4},{value:"\u2696\ufe0f Balances",id:"\ufe0f-balances",level:4},{value:"Part two",id:"part-two",level:2},{value:"\ud83e\udeb6\xa0Run a Celestia light node",id:"run-a-celestia-light-node",level:3},{value:"\ud83d\udcac\xa0Say gm world",id:"say-gm-world",level:3},{value:"\u270b\xa0Create your first query",id:"create-your-first-query",level:4},{value:"\ud83d\udce8\xa0Query request and response types",id:"query-request-and-response-types",level:4},{value:"\ud83d\udc4b\xa0Gm keeper function",id:"gm-keeper-function",level:4},{value:"\ud83d\udfe2\xa0Start your sovereign rollup",id:"start-your-sovereign-rollup",level:4},{value:"Clear previous chain history",id:"clear-previous-chain-history",level:5},{value:"Start the new chain",id:"start-the-new-chain",level:5}],c={toc:m};function d(e){let{components:t,...i}=e;return(0,o.kt)("wrapper",(0,a.Z)({},c,i,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"gm-world-rollup"},"GM world rollup"),(0,o.kt)("h2",{id:"\ufe0f-introduction"},"\u2600\ufe0f Introduction"),(0,o.kt)("p",null,"In this tutorial, we will build a sovereign ",(0,o.kt)("inlineCode",{parentName:"p"},"gm-world")," rollup using Rollkit\nand Celestia\u2019s data availability and consensus layer to submit Rollkit blocks."),(0,o.kt)("p",null,"This tutorial will cover setting up Ignite CLI,\nbuilding a Cosmos-SDK application-specific rollup blockchain,\nand posting data to Celestia.\nFirst, we will test on a local DA network and then we will deploy to a live\ntestnet."),(0,o.kt)("p",null,"The ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cosmos/cosmos-sdk"},"Cosmos SDK")," is a framework for\nbuilding blockchain applications. The Cosmos Ecosystem uses\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cosmos/ibc-go"},"Inter-Blockchain Communication (IBC)"),"\nto allow blockchains to communicate with one another."),(0,o.kt)("p",null,"The development journey for your rollup will look something like this:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#part-one"},"Part one"),": Run your rollup and post DA to a local devnet, and make sure everything works as expected"),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#part-two"},"Part two"),": Deploy the rollup, posting to a DA testnet. Confirm again that everything is functioning properly"),(0,o.kt)("li",{parentName:"ol"},"Coming soon: Deploy your rollup to the DA layer's mainnet")),(0,o.kt)("admonition",{title:"note",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This tutorial will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"Issue ticket"),"\nor let us know in our ",(0,o.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),".")),(0,o.kt)("admonition",{title:"caution",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The scripts for this tutorial are built for Celestia's\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspacerace testnet"),".\nIf you choose to use Mocha testnet or Arabica devnet,\nyou will need to modify the script manually.")),(0,o.kt)("h2",{id:"-what-is-gm"},"\ud83e\udd14 What is GM?"),(0,o.kt)("p",null,'GM means good morning. It\'s GM o\'clock somewhere, so there\'s never a bad time\nto say GM, Gm, or gm. You can think of "GM" as the new version of\n"hello world".'),(0,o.kt)("h2",{id:"dependencies"},"Dependencies"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Operating systems: GNU/Linux or macOS"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://go.dev"},"Golang")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/ignite/cli"},"Ignite CLI v0.26.1")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://brew.sh"},"Homebrew")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://www.gnu.org/software/wget"},"wget")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://stedolan.github.io/jq"},"jq")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://docs.celestia.org/nodes/light-node"},"A Celestia Light Node"))),(0,o.kt)(l.Z,{groupId:"network",mdxType:"Tabs"},(0,o.kt)(r.Z,{value:"linux",label:"Linux",mdxType:"TabItem"},(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you are only planning to complete ",(0,o.kt)("a",{parentName:"p",href:"#part-one"},"Part one"),",\nfeel free to skip to the ",(0,o.kt)("a",{parentName:"p",href:"#part-two"},"Part two"),"."),(0,o.kt)("p",{parentName:"admonition"},"Be sure to use the same testnet installation instructions through this\nentire tutorial.")),(0,o.kt)("h4",{id:"install-golang-on-linux"},"\ud83c\udfc3\xa0Install Golang on Linux"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/celestia-app"},"Celestia-App"),",\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/celestia-node"},"Celestia-Node"),",\nand ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cosmos/cosmos-sdk"},"Cosmos-SDK")," are\nwritten in the Golang programming language. You will need\nGolang to build and run them."),(0,o.kt)("p",null,"You can ",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment#install-golang"},"install Golang here"),"."),(0,o.kt)("h4",{id:"install-ignite-cli-on-linux"},"\ud83d\udd25\xa0Install Ignite CLI on Linux"),(0,o.kt)("p",null,"First, you will need to create ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/local/bin")," if you have not already:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo mkdir -p -m 775 /usr/local/bin\n")),(0,o.kt)("p",null,"Run this command in your terminal to install Ignite CLI:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl https://get.ignite.com/cli@v0.26.1! | bash\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u270b On some machines, you may run into permissions errors like the one below.\nYou can resolve this error by following the guidance\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.ignite.com/v0.25.2/guide/install#write-permission"},"here")," or below.")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"# Error\njcs @ ~ % curl https://get.ignite.com/cli@v0.26.1! | bash\n\n\n % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 3967 0 3967 0 0 16847 0 --:--:-- --:--:-- --:--:-- 17475\nInstalling ignite v0.26.1.....\n######################################################################## 100.0%\nmv: rename ./ignite to /usr/local/bin/ignite: Permission denied\n============\nError: mv failed\n")),(0,o.kt)("p",null,"The following command will resolve the permissions error:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo curl https://get.ignite.com/cli@v0.26.1! | sudo bash\n")),(0,o.kt)("p",null,"A successful installation will return something similar the response below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"}," % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 3967 0 3967 0 0 15586 0 --:--:-- --:--:-- --:--:-- 15931\nInstalling ignite v0.26.1.....\n######################################################################## 100.0%\nInstalled at /usr/local/bin/ignite\n")),(0,o.kt)("p",null,"Verify you\u2019ve installed Ignite CLI by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"ignite version\n")),(0,o.kt)("p",null,"The response that you receive should look something like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"jcs @ ~ % ignite version\nIgnite CLI version: v0.26.1\nIgnite CLI build date: 2022-10-20T15:52:00Z\nIgnite CLI source hash: cc393a9b59a8792b256432fafb472e5ac0738f7c\nCosmos SDK version: v0.46.3\nYour OS: darwin\nYour arch: arm64\nYour Node.js version: v18.10.0\nYour go version: go version go1.19.2 darwin/arm64\nYour uname -a: Darwin Joshs-MacBook-Air.local 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:20:07 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T8110 arm64\nYour cwd: /Users/joshstein\nIs on Gitpod: false\n"))),(0,o.kt)(r.Z,{value:"mac",label:"Mac",mdxType:"TabItem"},(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you are only planning to complete ",(0,o.kt)("a",{parentName:"p",href:"#part-one"},"Part one"),",\nfeel free to skip to the ",(0,o.kt)("a",{parentName:"p",href:"#part-two"},"Part two"),"."),(0,o.kt)("p",{parentName:"admonition"},"Be sure to use the same testnet installation instructions through this\nentire tutorial.")),(0,o.kt)("h4",{id:"install-golang-on-macos"},"\ud83c\udfc3\xa0Install Golang on macOS"),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/celestia-app"},"Celestia-App"),",\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/celestia-node"},"Celestia-Node"),",\nand ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cosmos/cosmos-sdk"},"Cosmos-SDK")," are\nwritten in the Golang programming language. You will need\nGolang to build and run them."),(0,o.kt)("p",null,"You can ",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment#install-golang"},"install Golang here"),"."),(0,o.kt)("h4",{id:"install-ignite-cli-on-macos"},"\ud83d\udd25\xa0Install Ignite CLI on macOS"),(0,o.kt)("p",null,"First, you will need to create ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/local/bin")," if you have not already:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo mkdir -p -m 775 /usr/local/bin\n")),(0,o.kt)("p",null,"Run this command in your terminal to install Ignite CLI:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl https://get.ignite.com/cli@v0.26.1! | bash\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"\u270b On some machines, you may run into permissions errors like the one below.\nYou can resolve this error by following the guidance\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.ignite.com/v0.25.2/guide/install#write-permission"},"here")," or below.")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"# Error\njcs @ ~ % curl https://get.ignite.com/cli@v0.26.1! | bash\n\n\n % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 3967 0 3967 0 0 16847 0 --:--:-- --:--:-- --:--:-- 17475\nInstalling ignite v0.26.1.....\n######################################################################## 100.0%\nmv: rename ./ignite to /usr/local/bin/ignite: Permission denied\n============\nError: mv failed\n")),(0,o.kt)("p",null,"The following command will resolve the permissions error:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo curl https://get.ignite.com/cli@v0.26.1! | sudo bash\n")),(0,o.kt)("p",null,"A successful installation will return something similar the response below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"}," % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 3967 0 3967 0 0 15586 0 --:--:-- --:--:-- --:--:-- 15931\nInstalling ignite v0.26.1.....\n######################################################################## 100.0%\nInstalled at /usr/local/bin/ignite\n")),(0,o.kt)("p",null,"Verify you\u2019ve installed Ignite CLI by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"ignite version\n")),(0,o.kt)("p",null,"The response that you receive should look something like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"jcs @ ~ % ignite version\nIgnite CLI version: v0.26.1\nIgnite CLI build date: 2023-01-24T18:50:18Z\nIgnite CLI source hash: d2a2e287c176ba010557f0b8fbaa198cdeee928d\nIgnite CLI config version: v1\nCosmos SDK version: v0.46.7\nYour OS: darwin\nYour arch: arm64\nYour Node.js version: v16.15.1\nYour go version: go version go1.20.2 darwin/arm64\nYour uname -a: Darwin Joshs-Air 22.5.0 Darwin Kernel Version 22.5.0: Thu Jun 8 22:21:34 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T8112 arm64\nYour cwd: /Users/joshstein\nIs on Gitpod: false\n")),(0,o.kt)("h4",{id:"install-homebrew-on-macos"},"\ud83c\udf7a\xa0Install Homebrew on macOS"),(0,o.kt)("p",null,"Homebrew will allow us to install dependencies for our Mac:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\n')),(0,o.kt)("p",null,"Be sure to run the commands similar to the output below from the successful installation:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"==> Next steps:\n- Run these three commands in your terminal to add Homebrew to your PATH:\n echo '# Set PATH, MANPATH, etc., for Homebrew.' >> /Users/joshstein/.zprofile\n echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users/joshstein/.zprofile\n eval \"$(/opt/homebrew/bin/brew shellenv)\"\n")),(0,o.kt)("h4",{id:"install-wget-and-jq-on-macos"},"\ud83c\udfc3\xa0Install wget and jq on macOS"),(0,o.kt)("p",null,"wget is an Internet file retriever and jq is a lightweight and flexible\ncommand-line JSON processor."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"brew install wget && brew install jq\n")))),(0,o.kt)("h2",{id:"part-one"},"Part one"),(0,o.kt)("p",null,"This part of the tutorial will teach developers how to easily run a local data availability (DA) devnet on their own machine (or in the cloud).\n",(0,o.kt)("strong",{parentName:"p"},"Running a local devnet for DA to test your rollup is the recommended first step before deploying to a testnet."),"\nThis eliminates the need for testnet tokens and deploying to a testnet until you are ready."),(0,o.kt)("admonition",{title:"Note",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Part one of the tutorial has only been tested on an AMD machine running Ubuntu 22.10 x64.")),(0,o.kt)("p",null,"Whether you're a developer simply testing things on your laptop or using a virtual machine in the cloud,\nthis process can be done on any machine of your choosing. We tested out the Devnet section (Part one) on a machine with the following specs:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Memory: 1 GB RAM"),(0,o.kt)("li",{parentName:"ul"},"CPU: Single Core AMD"),(0,o.kt)("li",{parentName:"ul"},"Disk: 25 GB SSD Storage"),(0,o.kt)("li",{parentName:"ul"},"OS: Ubuntu 22.10 x64")),(0,o.kt)("h3",{id:"-prerequisites"},"\ud83d\udcbb Prerequisites"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker"},"Docker")," installed on your machine")),(0,o.kt)("h3",{id:"-running-local-devnet-with-a-rollkit-rollup"},"\ud83c\udfe0 Running local devnet with a Rollkit rollup"),(0,o.kt)("p",null,"First, run the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/local-celestia-devnet"},(0,o.kt)("inlineCode",{parentName:"a"},"local-celestia-devnet"))," by running the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker run --platform linux/amd64 -p 26650:26657 -p 26659:26659 ghcr.io/rollkit/local-celestia-devnet:v0.9.1\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Port 26657 on the Docker container in this example will be mapped to the local port 26650. This is to avoid clashing ports with\nthe Rollkit node, as we're running the devnet and node on one machine.")),(0,o.kt)("h3",{id:"-query-your-balance"},"\ud83d\udd0e Query your balance"),(0,o.kt)("p",null,"Open a new terminal instance. Check the balance on your account that you'll be using to post blocks to the\nlocal network, this will make sure you can post rollup blocks to your Celestia Devnet for DA & consensus:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl -X GET http://0.0.0.0:26659/balance\n")),(0,o.kt)("p",null,"You will see something like this, denoting your balance in TIA x 10",(0,o.kt)("sup",null,"-6"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'{"denom":"utia","amount":"999995000000000"}\n')),(0,o.kt)("p",null,"If you want to be able to transpose your JSON results in a nicer format, you can install ",(0,o.kt)("a",{parentName:"p",href:"https://stedolan.github.io/jq/"},(0,o.kt)("inlineCode",{parentName:"a"},"jq")),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install jq\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We'll need ",(0,o.kt)("inlineCode",{parentName:"p"},"jq")," later, so install it!")),(0,o.kt)("p",null,"Then run this to prettify the result:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl -X GET http://0.0.0.0:26659/balance | jq\n")),(0,o.kt)("p",null,"Here's what my response was when I wrote this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},' % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 43 100 43 0 0 1730 0 --:--:-- --:--:-- --:--:-- 1791\n{\n "denom": "utia",\n "amount": "999995000000000"\n}\n')),(0,o.kt)("p",null,"If you want to clean it up some more, you can use the ",(0,o.kt)("inlineCode",{parentName:"p"},"-s")," option to run ",(0,o.kt)("inlineCode",{parentName:"p"},"curl")," in silent mode and not print the progress metrics:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl -s -X GET http://0.0.0.0:26659/balance | jq\n")),(0,o.kt)("p",null,"Your result will now look like this, nice \ud83e\udee1"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'{\n "denom": "utia",\n "amount": "999995000000000"\n}\n')),(0,o.kt)("h3",{id:"-start-stop-or-remove-your-container"},"\ud83d\udfe2 Start, stop, or remove your container"),(0,o.kt)("p",null,"Find the Container ID that is running by using the command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker ps\n")),(0,o.kt)("p",null,"Then stop the container:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker stop CONTAINER_ID_or_NAME\n")),(0,o.kt)("p",null,"You can obtain the container ID or name of a stopped container using the ",(0,o.kt)("inlineCode",{parentName:"p"},"docker ps -a")," command, which will list all containers (running and stopped) and their details. For example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker ps -a\n")),(0,o.kt)("p",null,"This will give you an output similar to this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\nd9af68de54e4 ghcr.io/rollkit/local-celestia-devnet:v0.9.1 "/entrypoint.sh" 5 minutes ago Up 2 minutes 1317/tcp, 9090/tcp, 0.0.0.0:26657->26657/tcp, :::26657->26657/tcp, 26656/tcp, 0.0.0.0:26659->26659/tcp, :::26659->26659/tcp musing_matsumoto\n')),(0,o.kt)("p",null,"In this example, you can restart the container using either its container ID (",(0,o.kt)("inlineCode",{parentName:"p"},"d9af68de54e4"),") or name (",(0,o.kt)("inlineCode",{parentName:"p"},"musing_matsumoto"),"). To restart the container, run:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker start d9af68de54e4\n")),(0,o.kt)("p",null,"or"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker start musing_matsumoto\n")),(0,o.kt)("p",null,"If you ever would like to remove the container, you can use the ",(0,o.kt)("inlineCode",{parentName:"p"},"docker rm")," command followed by the container ID or name."),(0,o.kt)("p",null,"Here is an example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"docker rm CONTAINER_ID_or_NAME\n")),(0,o.kt)("h3",{id:"\ufe0f-building-your-sovereign-rollup"},"\ud83c\udfd7\ufe0f Building your sovereign rollup"),(0,o.kt)("p",null,"Now that you have a Celestia devnet running, you are ready to install Golang. We will use Golang to build and run our Cosmos-SDK blockchain."),(0,o.kt)("p",null,"The Ignite CLI comes with scaffolding commands to make development of\nblockchains quicker by creating everything that is needed to start a new\nCosmos SDK blockchain."),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment#install-golang"},"Install Golang")," (",(0,o.kt)("em",{parentName:"p"},"these commands are for amd64/linux"),"):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'cd $HOME\nver="1.19.1"\nwget "https://golang.org/dl/go$ver.linux-amd64.tar.gz"\nsudo rm -rf /usr/local/go\nsudo tar -C /usr/local -xzf "go$ver.linux-amd64.tar.gz"\nrm "go$ver.linux-amd64.tar.gz"\necho "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile\nsource $HOME/.bash_profile\ngo version\n')),(0,o.kt)("p",null,"Now, use the following command to install Ignite CLI:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl https://get.ignite.com/cli@v0.26.1! | bash\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you have issues with installation, the full guide can be found ",(0,o.kt)("a",{parentName:"p",href:"https://get.ignite.com/cli"},"here")," or on ",(0,o.kt)("a",{parentName:"p",href:"https://docs.ignite.com"},"docs.ignite.com"),".\nThe above command was tested on ",(0,o.kt)("inlineCode",{parentName:"p"},"amd64/linux"),".")),(0,o.kt)("p",null,"Check your version:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"ignite version\n")),(0,o.kt)("p",null,"Open a new tab or window in your terminal and run this command to\nscaffold your rollup. Scaffold the chain:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd $HOME\nignite scaffold chain gm --address-prefix gm\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"--address-prefix gm")," flag will change the address prefix from ",(0,o.kt)("inlineCode",{parentName:"p"},"cosmos")," to ",(0,o.kt)("inlineCode",{parentName:"p"},"gm"),". Read more on the ",(0,o.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/v0.46/basics/accounts.html"},"Cosmos docs"),".")),(0,o.kt)("p",null,"The response will look similar to below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"jcs @ ~ % ignite scaffold chain gm --address-prefix gm\n\n\u2b50\ufe0f Successfully created a new blockchain 'gm'.\n\ud83d\udc49 Get started with the following commands:\n\n % cd gm\n % ignite chain serve\n\nDocumentation: https://docs.ignite.com\n")),(0,o.kt)("p",null,"This command has created a Cosmos SDK blockchain in the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory. The\n",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory contains a fully functional blockchain. The following standard\nCosmos SDK ",(0,o.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main/modules"},"modules")," have been\nimported:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"staking")," - for delegated Proof-of-Stake (PoS) consensus mechanism"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"bank")," - for fungible token transfers between accounts"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"gov")," - for on-chain governance"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"mint")," - for minting new units of staking token"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"nft")," - for creating, transferring, and updating NFTs"),(0,o.kt)("li",{parentName:"ul"},"and ",(0,o.kt)("a",{parentName:"li",href:"https://docs.cosmos.network/main/architecture/adr-043-nft-module.html"},"more"))),(0,o.kt)("p",null,"Change to the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd gm\n")),(0,o.kt)("p",null,"You can learn more about the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory\u2019s file structure ",(0,o.kt)("a",{parentName:"p",href:"https://docs.ignite.com/v0.25.2/guide/hello#blockchain-directory-structure"},"here"),".\nMost of our work in this tutorial will happen in the ",(0,o.kt)("inlineCode",{parentName:"p"},"x")," directory."),(0,o.kt)("h3",{id:"\ufe0f-install-rollkit"},"\ud83d\uddde\ufe0f Install Rollkit"),(0,o.kt)("p",null,"To swap out Tendermint for Rollkit, run the following command\nfrom inside the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs\ngo mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d\ngo mod tidy\ngo mod download\n")),(0,o.kt)("h3",{id:"\ufe0f-start-your-rollup"},"\u25b6\ufe0f Start your rollup"),(0,o.kt)("p",null,"Download the ",(0,o.kt)("inlineCode",{parentName:"p"},"init.sh")," script to start the chain:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"# From inside the `gm` directory\nwget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/gm/init-local.sh\n")),(0,o.kt)("p",null,"Run the ",(0,o.kt)("inlineCode",{parentName:"p"},"init-local.sh")," script:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"bash init-local.sh\n")),(0,o.kt)("p",null,"This will start your rollup, connected to the local Celestia devnet you have running."),(0,o.kt)("p",null,"Now let's explore a bit."),(0,o.kt)("h4",{id:"-keys"},"\ud83d\udd11 Keys"),(0,o.kt)("p",null,"List your keys:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd keys list --keyring-backend test\n")),(0,o.kt)("p",null,"You should see an output like the following"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'- address: gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7\n name: gm-key-2\n pubkey: \'{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AlXXb6Op8DdwCejeYkGWbF4G3pDLDO+rYiVWKPKuvYaz"}\'\n type: local\n- address: gm13nf52x452c527nycahthqq4y9phcmvat9nejl2\n name: gm-key\n pubkey: \'{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AwigPerY+eeC2WAabA6iW1AipAQora5Dwmo1SnMnjavt"}\'\n type: local\n')),(0,o.kt)("h4",{id:"-transactions"},"\ud83d\udcb8 Transactions"),(0,o.kt)("p",null,"Now we can test sending a transaction from one of our keys to the other. We can do that with the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd tx bank send [from_key_or_address] [to_address] [amount] [flags]\n")),(0,o.kt)("p",null,"Set your keys as variables to make it easier to add the address:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"export KEY1=gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7\nexport KEY2=gm13nf52x452c527nycahthqq4y9phcmvat9nejl2\n")),(0,o.kt)("p",null,"So using our information from the ",(0,o.kt)("a",{parentName:"p",href:"#keys"},"keys")," command, we can construct the transaction command like so to send 42069stake from one address to another:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd tx bank send $KEY1 $KEY2 42069stake --keyring-backend test\n")),(0,o.kt)("p",null,"You'll be prompted to accept the transaction:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'auth_info:\n fee:\n amount: []\n gas_limit: "200000"\n granter: ""\n payer: ""\n signer_infos: []\n tip: null\nbody:\n extension_options: []\n memo: ""\n messages:\n - \'@type\': /cosmos.bank.v1beta1.MsgSend\n amount:\n - amount: "42069"\n denom: stake\n from_address: gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7\n to_address: gm13nf52x452c527nycahthqq4y9phcmvat9nejl2\n non_critical_extension_options: []\n timeout_height: "0"\nsignatures: []\nconfirm transaction before signing and broadcasting [y/N]:\n')),(0,o.kt)("p",null,"Type ",(0,o.kt)("inlineCode",{parentName:"p"},"y")," if you'd like to confirm and sign the transaction. Then, you'll see the confirmation:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'code: 0\ncodespace: ""\ndata: ""\nevents: []\ngas_used: "0"\ngas_wanted: "0"\nheight: "0"\ninfo: ""\nlogs: []\nraw_log: \'[]\'\ntimestamp: ""\ntx: null\ntxhash: 677CAF6C80B85ACEF6F9EC7906FB3CB021322AAC78B015FA07D5112F2F824BFF\n')),(0,o.kt)("h4",{id:"\ufe0f-balances"},"\u2696\ufe0f Balances"),(0,o.kt)("p",null,"Then, query your balance:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd query bank balances $KEY2\n")),(0,o.kt)("p",null,"This is the key that received the balance, so it should have increased past the initial ",(0,o.kt)("inlineCode",{parentName:"p"},"STAKING_AMOUNT"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'balances:\n- amount: "10000000000000000000042069"\n denom: stake\npagination:\n next_key: null\n total: "0"\n')),(0,o.kt)("p",null,"The other key, should have decreased in balance:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd query bank balances $KEY1\n")),(0,o.kt)("p",null,"Response:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'balances:\n- amount: "9999999999999999999957931"\n denom: stake\npagination:\n next_key: null\n total: "0"\n')),(0,o.kt)("h2",{id:"part-two"},"Part two"),(0,o.kt)("h3",{id:"run-a-celestia-light-node"},"\ud83e\udeb6\xa0Run a Celestia light node"),(0,o.kt)("p",null,"Follow instructions to install and start your Celestia Data Availalbility\nlayer Light Node selecting the network that you had previously used. You can\nfind instructions to install and run the node ",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/light-node"},"here"),"."),(0,o.kt)("p",null,"After you have Go and Ignite CLI installed, and your Celestia Light\nNode running on your machine, you're ready to build, test, and launch your own\nsovereign rollup."),(0,o.kt)("h3",{id:"say-gm-world"},"\ud83d\udcac\xa0Say gm world"),(0,o.kt)("p",null,"Now, we're going to get our blockchain to say ",(0,o.kt)("inlineCode",{parentName:"p"},"gm world!")," - in order to do so\nyou need to make the following changes:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Modify a protocol buffer file"),(0,o.kt)("li",{parentName:"ul"},"Create a keeper query function that returns data")),(0,o.kt)("p",null,"Protocol buffer files contain proto RPC calls that define Cosmos SDK queries\nand message handlers, and proto messages that define Cosmos SDK types. The RPC\ncalls are also responsible for exposing an HTTP API."),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"Keeper")," is required for each Cosmos SDK module and is an abstraction for\nmodifying the state of the blockchain. Keeper functions allow us to query or\nwrite to the state."),(0,o.kt)("h4",{id:"create-your-first-query"},"\u270b\xa0Create your first query"),(0,o.kt)("p",null,(0,o.kt)("strong",{parentName:"p"},"Open a new terminal instance that is not the\nsame that you started the chain in.")),(0,o.kt)("p",null,"In your new terminal, ",(0,o.kt)("inlineCode",{parentName:"p"},"cd")," into the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," directory and run this command\nto create the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," query:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold query gm --response text\n")),(0,o.kt)("p",null,"Response:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"modify proto/gm/gm/query.proto\nmodify x/gm/client/cli/query.go\ncreate x/gm/client/cli/query_gm.go\ncreate x/gm/keeper/query_gm.go\n\n\ud83c\udf89 Created a query `gm`.\n")),(0,o.kt)("p",null,"What just happened? ",(0,o.kt)("inlineCode",{parentName:"p"},"query")," accepts the name of the query (",(0,o.kt)("inlineCode",{parentName:"p"},"gm"),"), an optional\nlist of request parameters (empty in this tutorial), and an optional\ncomma-separated list of response field with a ",(0,o.kt)("inlineCode",{parentName:"p"},"--response")," flag (",(0,o.kt)("inlineCode",{parentName:"p"},"text")," in this\ntutorial)."),(0,o.kt)("p",null,"Navigate to the ",(0,o.kt)("inlineCode",{parentName:"p"},"gm/proto/gm/gm/query.proto")," file, you\u2019ll see that ",(0,o.kt)("inlineCode",{parentName:"p"},"Gm")," RPC has\nbeen added to the ",(0,o.kt)("inlineCode",{parentName:"p"},"Query")," service:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="gm/proto/gm/gm/query.proto"',title:'"gm/proto/gm/gm/query.proto"'},'service Query {\n rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {\n option (google.api.http).get = "/gm/gm/params";\n }\n rpc Gm(QueryGmRequest) returns (QueryGmResponse) {\n option (google.api.http).get = "/gm/gm/gm";\n }\n}\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"Gm")," RPC for the ",(0,o.kt)("inlineCode",{parentName:"p"},"Query")," service:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"is responsible for returning a ",(0,o.kt)("inlineCode",{parentName:"li"},"text")," string"),(0,o.kt)("li",{parentName:"ul"},"Accepts request parameters (",(0,o.kt)("inlineCode",{parentName:"li"},"QueryGmRequest"),")"),(0,o.kt)("li",{parentName:"ul"},"Returns response of type ",(0,o.kt)("inlineCode",{parentName:"li"},"QueryGmResponse")),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"option")," defines the endpoint that is used by gRPC to generate an HTTP API")),(0,o.kt)("h4",{id:"query-request-and-response-types"},"\ud83d\udce8\xa0Query request and response types"),(0,o.kt)("p",null,"In the same file, we will find:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"QueryGmRequest")," is empty because it does not require parameters"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"QueryGmResponse")," contains ",(0,o.kt)("inlineCode",{parentName:"li"},"text")," that is returned from the chain")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="gm/proto/gm/gm/query.proto"',title:'"gm/proto/gm/gm/query.proto"'},"message QueryGmRequest {\n}\n\nmessage QueryGmResponse {\n string text = 1;\n}\n")),(0,o.kt)("h4",{id:"gm-keeper-function"},"\ud83d\udc4b\xa0Gm keeper function"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"gm/x/gm/keeper/query_gm.go")," file contains the ",(0,o.kt)("inlineCode",{parentName:"p"},"Gm")," keeper function that\nhandles the query and returns data."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="gm/x/gm/keeper/query_gm.go"',title:'"gm/x/gm/keeper/query_gm.go"'},'func (k Keeper) Gm(goCtx context.Context, req *types.QueryGmRequest) (*types.QueryGmResponse, error) {\n if req == nil {\n return nil, status.Error(codes.InvalidArgument, "invalid request")\n }\n ctx := sdk.UnwrapSDKContext(goCtx)\n _ = ctx\n return &types.QueryGmResponse{}, nil\n}\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"Gm")," function performs the following actions:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Makes a basic check on the request and throws an error if it\u2019s ",(0,o.kt)("inlineCode",{parentName:"li"},"nil")),(0,o.kt)("li",{parentName:"ul"},"Stores context in a ",(0,o.kt)("inlineCode",{parentName:"li"},"ctx")," variable that contains information about the\nenvironment of the request"),(0,o.kt)("li",{parentName:"ul"},"Returns a response of type ",(0,o.kt)("inlineCode",{parentName:"li"},"QueryGmResponse"))),(0,o.kt)("p",null,"Currently, the response is empty and you'll need to update the keeper function."),(0,o.kt)("p",null,"Our ",(0,o.kt)("inlineCode",{parentName:"p"},"query.proto")," file defines that the response accepts ",(0,o.kt)("inlineCode",{parentName:"p"},"text"),". Use your text\neditor to modify the keeper function in ",(0,o.kt)("inlineCode",{parentName:"p"},"gm/x/gm/keeper/query_gm.go")," ."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="gm/x/gm/keeper/query_gm.go"',title:'"gm/x/gm/keeper/query_gm.go"'},'func (k Keeper) Gm(goCtx context.Context, req *types.QueryGmRequest) (*types.QueryGmResponse, error) {\n if req == nil {\n return nil, status.Error(codes.InvalidArgument, "invalid request")\n }\n ctx := sdk.UnwrapSDKContext(goCtx)\n _ = ctx\n return &types.QueryGmResponse{Text: "gm world!"}, nil\n}\n')),(0,o.kt)("h4",{id:"start-your-sovereign-rollup"},"\ud83d\udfe2\xa0Start your sovereign rollup"),(0,o.kt)("admonition",{title:"caution",type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"Before starting our rollup, we'll need to find and change\n",(0,o.kt)("inlineCode",{parentName:"p"},"FlagIAVLFastNode")," to ",(0,o.kt)("inlineCode",{parentName:"p"},"FlagDisableIAVLFastNode"),":"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="gm/cmd/gmd/cmd/root.go"',title:'"gm/cmd/gmd/cmd/root.go"'},"baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(server.FlagDisableIAVLFastNode))),\n"))),(0,o.kt)("p",null,"We have a handy ",(0,o.kt)("inlineCode",{parentName:"p"},"init-testnet.sh")," found in this repo\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/tree/main/docs/scripts/gm"},"here"),"."),(0,o.kt)("p",null,"We can copy it over to our directory with the following commands:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"# From inside the `gm` directory\nwget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/gm/init-testnet.sh\n")),(0,o.kt)("p",null,"This copies over our ",(0,o.kt)("inlineCode",{parentName:"p"},"init-testnet.sh")," script to initialize our\n",(0,o.kt)("inlineCode",{parentName:"p"},"gm")," rollup."),(0,o.kt)("p",null,"You can view the contents of the script to see how we\ninitialize the gm rollup."),(0,o.kt)("h5",{id:"clear-previous-chain-history"},"Clear previous chain history"),(0,o.kt)("p",null,"Before starting the rollup, we need to remove the old project folders:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cd $HOME\nrm -r go/bin/gmd && rm -rf .gm\n")),(0,o.kt)("h5",{id:"start-the-new-chain"},"Start the new chain"),(0,o.kt)("p",null,"Now, you can initialize the script with the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"bash init-testnet.sh\n")),(0,o.kt)("p",null,"With that, we have kickstarted our second ",(0,o.kt)("inlineCode",{parentName:"p"},"gmd")," network!"),(0,o.kt)("p",null,"The\xa0",(0,o.kt)("inlineCode",{parentName:"p"},"query"),"\xa0command has also scaffolded\n",(0,o.kt)("inlineCode",{parentName:"p"},"x/gm/client/cli/query_gm.go"),"\xa0that\nimplements a CLI equivalent of the gm query and mounted this command in\n",(0,o.kt)("inlineCode",{parentName:"p"},"x/gm/client/cli/query.go"),"."),(0,o.kt)("p",null,"In a separate window, run the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"gmd q gm gm\n")),(0,o.kt)("p",null,"We will get the following JSON response:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"text: gm world!\n")),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"4.png",src:n(7388).Z,width:"1064",height:"862"})),(0,o.kt)("p",null,"Congratulations \ud83c\udf89 you've successfully built your first rollup and queried it!"),(0,o.kt)("p",null,"If you're interested in looking at the demo repository\nfor this tutorial, you can at ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/gm"},"https://github.com/rollkit/gm"),"."))}d.isMDXComponent=!0},7388:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/4-856eac0d6cc770f822920d687f38f9e7.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/6048.4ec4ba27.js b/pr-preview/pr-192/assets/js/6048.4ec4ba27.js deleted file mode 100644 index ce411441d..000000000 --- a/pr-preview/pr-192/assets/js/6048.4ec4ba27.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6048],{9058:(e,t,a)=>{a.d(t,{Z:()=>N});var l=a(7294),n=a(6010),r=a(7676),o=a(7524),s=a(9960),c=a(5999);const m="sidebar_re4s",i="sidebarItemTitle_pO2u",u="sidebarItemList_Yudw",d="sidebarItem__DBe",g="sidebarItemLink_mo7H",p="sidebarItemLinkActive_I1ZP";function h(e){let{sidebar:t}=e;return l.createElement("aside",{className:"col col--3"},l.createElement("nav",{className:(0,n.Z)(m,"thin-scrollbar"),"aria-label":(0,c.I)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"})},l.createElement("div",{className:(0,n.Z)(i,"margin-bottom--md")},t.title),l.createElement("ul",{className:(0,n.Z)(u,"clean-list")},t.items.map((e=>l.createElement("li",{key:e.permalink,className:d},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:g,activeClassName:p},e.title)))))))}var E=a(3102);function f(e){let{sidebar:t}=e;return l.createElement("ul",{className:"menu__list"},t.items.map((e=>l.createElement("li",{key:e.permalink,className:"menu__list-item"},l.createElement(s.Z,{isNavLink:!0,to:e.permalink,className:"menu__link",activeClassName:"menu__link--active"},e.title)))))}function b(e){return l.createElement(E.Zo,{component:f,props:e})}function v(e){let{sidebar:t}=e;const a=(0,o.i)();return t?.items.length?"mobile"===a?l.createElement(b,{sidebar:t}):l.createElement(h,{sidebar:t}):null}function N(e){const{sidebar:t,toc:a,children:o,...s}=e,c=t&&t.items.length>0;return l.createElement(r.Z,s,l.createElement("div",{className:"container margin-vert--lg"},l.createElement("div",{className:"row"},l.createElement(v,{sidebar:t}),l.createElement("main",{className:(0,n.Z)("col",{"col--7":c,"col--9 col--offset-1":!c}),itemScope:!0,itemType:"http://schema.org/Blog"},o),a&&l.createElement("div",{className:"col col--2"},a))))}},390:(e,t,a)=>{a.d(t,{Z:()=>x});var l=a(7294),n=a(6010),r=a(9460),o=a(4996);function s(e){let{children:t,className:a}=e;const{frontMatter:n,assets:s}=(0,r.C)(),{withBaseUrl:c}=(0,o.C)(),m=s.image??n.image;return l.createElement("article",{className:a,itemProp:"blogPost",itemScope:!0,itemType:"http://schema.org/BlogPosting"},m&&l.createElement("meta",{itemProp:"image",content:c(m,{absolute:!0})}),t)}var c=a(9960);const m="title_f1Hy";function i(e){let{className:t}=e;const{metadata:a,isBlogPostPage:o}=(0,r.C)(),{permalink:s,title:i}=a,u=o?"h1":"h2";return l.createElement(u,{className:(0,n.Z)(m,t),itemProp:"headline"},o?i:l.createElement(c.Z,{itemProp:"url",to:s},i))}var u=a(5999),d=a(8824);const g="container_mt6G";function p(e){let{readingTime:t}=e;const a=function(){const{selectMessage:e}=(0,d.c)();return t=>{const a=Math.ceil(t);return e(a,(0,u.I)({id:"theme.blog.post.readingTime.plurals",description:'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One min read|{readingTime} min read"},{readingTime:a}))}}();return l.createElement(l.Fragment,null,a(t))}function h(e){let{date:t,formattedDate:a}=e;return l.createElement("time",{dateTime:t,itemProp:"datePublished"},a)}function E(){return l.createElement(l.Fragment,null," \xb7 ")}function f(e){let{className:t}=e;const{metadata:a}=(0,r.C)(),{date:o,formattedDate:s,readingTime:c}=a;return l.createElement("div",{className:(0,n.Z)(g,"margin-vert--md",t)},l.createElement(h,{date:o,formattedDate:s}),void 0!==c&&l.createElement(l.Fragment,null,l.createElement(E,null),l.createElement(p,{readingTime:c})))}function b(e){return e.href?l.createElement(c.Z,e):l.createElement(l.Fragment,null,e.children)}function v(e){let{author:t,className:a}=e;const{name:r,title:o,url:s,imageURL:c,email:m}=t,i=s||m&&`mailto:${m}`||void 0;return l.createElement("div",{className:(0,n.Z)("avatar margin-bottom--sm",a)},c&&l.createElement(b,{href:i,className:"avatar__photo-link"},l.createElement("img",{className:"avatar__photo",src:c,alt:r})),r&&l.createElement("div",{className:"avatar__intro",itemProp:"author",itemScope:!0,itemType:"https://schema.org/Person"},l.createElement("div",{className:"avatar__name"},l.createElement(b,{href:i,itemProp:"url"},l.createElement("span",{itemProp:"name"},r))),o&&l.createElement("small",{className:"avatar__subtitle",itemProp:"description"},o)))}const N="authorCol_Hf19",P="imageOnlyAuthorRow_pa_O",_="imageOnlyAuthorCol_G86a";function Z(e){let{className:t}=e;const{metadata:{authors:a},assets:o}=(0,r.C)();if(0===a.length)return null;const s=a.every((e=>{let{name:t}=e;return!t}));return l.createElement("div",{className:(0,n.Z)("margin-top--md margin-bottom--sm",s?P:"row",t)},a.map(((e,t)=>l.createElement("div",{className:(0,n.Z)(!s&&"col col--6",s?_:N),key:t},l.createElement(v,{author:{...e,imageURL:o.authorsImageUrls[t]??e.imageURL}})))))}function k(){return l.createElement("header",null,l.createElement(i,null),l.createElement(f,null),l.createElement(Z,null))}var C=a(8780),w=a(210);function T(e){let{children:t,className:a}=e;const{isBlogPostPage:o}=(0,r.C)();return l.createElement("div",{id:o?C.blogPostContainerID:void 0,className:(0,n.Z)("markdown",a),itemProp:"articleBody"},l.createElement(w.Z,null,t))}var y=a(4881),B=a(1526),I=a(7462);function F(){return l.createElement("b",null,l.createElement(u.Z,{id:"theme.blog.post.readMore",description:"The label used in blog post item excerpts to link to full blog posts"},"Read More"))}function M(e){const{blogPostTitle:t,...a}=e;return l.createElement(c.Z,(0,I.Z)({"aria-label":(0,u.I)({message:"Read more about {title}",id:"theme.blog.post.readMoreLabel",description:"The ARIA label for the link to full blog posts from excerpts"},{title:t})},a),l.createElement(F,null))}const L="blogPostFooterDetailsFull_mRVl";function R(){const{metadata:e,isBlogPostPage:t}=(0,r.C)(),{tags:a,title:o,editUrl:s,hasTruncateMarker:c}=e,m=!t&&c,i=a.length>0;return i||m||s?l.createElement("footer",{className:(0,n.Z)("row docusaurus-mt-lg",t&&L)},i&&l.createElement("div",{className:(0,n.Z)("col",{"col--9":m})},l.createElement(B.Z,{tags:a})),t&&s&&l.createElement("div",{className:"col margin-top--sm"},l.createElement(y.Z,{editUrl:s})),m&&l.createElement("div",{className:(0,n.Z)("col text--right",{"col--3":i})},l.createElement(M,{blogPostTitle:o,to:e.permalink}))):null}function x(e){let{children:t,className:a}=e;const o=function(){const{isBlogPostPage:e}=(0,r.C)();return e?void 0:"margin-bottom--xl"}();return l.createElement(s,{className:(0,n.Z)(o,a)},l.createElement(k,null),l.createElement(T,null,t),l.createElement(R,null))}},9460:(e,t,a)=>{a.d(t,{C:()=>s,n:()=>o});var l=a(7294),n=a(902);const r=l.createContext(null);function o(e){let{children:t,content:a,isBlogPostPage:n=!1}=e;const o=function(e){let{content:t,isBlogPostPage:a}=e;return(0,l.useMemo)((()=>({metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:a})),[t,a])}({content:a,isBlogPostPage:n});return l.createElement(r.Provider,{value:o},t)}function s(){const e=(0,l.useContext)(r);if(null===e)throw new n.i6("BlogPostProvider");return e}},8824:(e,t,a)=>{a.d(t,{c:()=>m});var l=a(7294),n=a(2263);const r=["zero","one","two","few","many","other"];function o(e){return r.filter((t=>e.includes(t)))}const s={locale:"en",pluralForms:o(["one","other"]),select:e=>1===e?"one":"other"};function c(){const{i18n:{currentLocale:e}}=(0,n.Z)();return(0,l.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:o(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${t.message}\n`),s}}),[e])}function m(){const e=c();return{selectMessage:(t,a)=>function(e,t,a){const l=e.split("|");if(1===l.length)return l[0];l.length>a.pluralForms.length&&console.error(`For locale=${a.locale}, a maximum of ${a.pluralForms.length} plural forms are expected (${a.pluralForms.join(",")}), but the message contains ${l.length}: ${e}`);const n=a.select(t),r=a.pluralForms.indexOf(n);return l[Math.min(r,l.length-1)]}(a,t,e)}}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/6875c492.f37b7b5c.js b/pr-preview/pr-192/assets/js/6875c492.f37b7b5c.js deleted file mode 100644 index a9486763b..000000000 --- a/pr-preview/pr-192/assets/js/6875c492.f37b7b5c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8610],{9703:(e,t,a)=>{a.d(t,{Z:()=>s});var n=a(7294),l=a(5999),r=a(2244);function s(e){const{metadata:t}=e,{previousPage:a,nextPage:s}=t;return n.createElement("nav",{className:"pagination-nav","aria-label":(0,l.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},a&&n.createElement(r.Z,{permalink:a,title:n.createElement(l.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),s&&n.createElement(r.Z,{permalink:s,title:n.createElement(l.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},9985:(e,t,a)=>{a.d(t,{Z:()=>s});var n=a(7294),l=a(9460),r=a(390);function s(e){let{items:t,component:a=r.Z}=e;return n.createElement(n.Fragment,null,t.map((e=>{let{content:t}=e;return n.createElement(l.n,{key:t.metadata.permalink,content:t},n.createElement(a,null,n.createElement(t,null)))})))}},1714:(e,t,a)=>{a.r(t),a.d(t,{default:()=>E});var n=a(7294),l=a(6010),r=a(5999),s=a(8824),o=a(1944),i=a(5281),g=a(9960),c=a(9058),m=a(9703),p=a(197),u=a(9985);function d(e){const t=function(){const{selectMessage:e}=(0,s.c)();return t=>e(t,(0,r.I)({id:"theme.blog.post.plurals",description:'Pluralized label for "{count} posts". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One post|{count} posts"},{count:t}))}();return(0,r.I)({id:"theme.blog.tagTitle",description:"The title of the page for a blog tag",message:'{nPosts} tagged with "{tagName}"'},{nPosts:t(e.count),tagName:e.label})}function h(e){let{tag:t}=e;const a=d(t);return n.createElement(n.Fragment,null,n.createElement(o.d,{title:a}),n.createElement(p.Z,{tag:"blog_tags_posts"}))}function b(e){let{tag:t,items:a,sidebar:l,listMetadata:s}=e;const o=d(t);return n.createElement(c.Z,{sidebar:l},n.createElement("header",{className:"margin-bottom--xl"},n.createElement("h1",null,o),n.createElement(g.Z,{href:t.allTagsPath},n.createElement(r.Z,{id:"theme.tags.tagsPageLink",description:"The label of the link targeting the tag list page"},"View All Tags"))),n.createElement(u.Z,{items:a}),n.createElement(m.Z,{metadata:s}))}function E(e){return n.createElement(o.FG,{className:(0,l.Z)(i.k.wrapper.blogPages,i.k.page.blogTagPostListPage)},n.createElement(h,e),n.createElement(b,e))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/7036.6d9b6d0a.js b/pr-preview/pr-192/assets/js/7036.6d9b6d0a.js deleted file mode 100644 index 8712b1009..000000000 --- a/pr-preview/pr-192/assets/js/7036.6d9b6d0a.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7036],{3905:(e,t,n)=>{"use strict";n.d(t,{Zo:()=>m,kt:()=>f});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),i=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},m=function(e){var t=i(e.components);return o.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,m=c(e,["components","mdxType","originalType","parentName"]),u=i(n),p=a,f=u["".concat(s,".").concat(p)]||u[p]||d[p]||r;return n?o.createElement(f,l(l({ref:t},m),{},{components:n})):o.createElement(f,l({ref:t},m))}));function f(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,l=new Array(r);l[0]=p;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c[u]="string"==typeof e?e:a,l[1]=c;for(var i=2;i{"use strict";n.d(t,{Z:()=>m});var o=n(7294),a=n(5999),r=n(5281),l=n(7462),c=n(6010);const s="iconEdit_Z9Sw";function i(e){let{className:t,...n}=e;return o.createElement("svg",(0,l.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,c.Z)(s,t),"aria-hidden":"true"},n),o.createElement("g",null,o.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function m(e){let{editUrl:t}=e;return o.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:r.k.common.editThisPage},o.createElement(i,null),o.createElement(a.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>m});var o=n(7462),a=n(7294),r=n(6010),l=n(5999),c=n(6668);const s="anchorWithStickyNavbar_LWe7",i="anchorWithHideOnScrollNavbar_WYt5";function m(e){let{as:t,id:n,...m}=e;const{navbar:{hideOnScroll:u}}=(0,c.L)();return"h1"!==t&&n?a.createElement(t,(0,o.Z)({},m,{className:(0,r.Z)("anchor",u?i:s),id:n}),m.children,a.createElement("a",{className:"hash-link",href:`#${n}`,title:(0,l.I)({id:"theme.common.headingLinkTitle",message:"Direct link to heading",description:"Title for link to heading"})},"\u200b")):a.createElement(t,(0,o.Z)({},m,{id:void 0}))}},210:(e,t,n)=>{"use strict";n.d(t,{Z:()=>ye});var o=n(7294),a=n(3905),r=n(7462),l=n(5742);var c=n(2389),s=n(6010),i=n(2949),m=n(6668);function u(){const{prism:e}=(0,m.L)(),{colorMode:t}=(0,i.I)(),n=e.theme,o=e.darkTheme||n;return"dark"===t?o:n}var d=n(5281),p=n(7594),f=n.n(p);const h=/title=(?["'])(?.*?)\1/,g=/\{(?<range>[\d,-]+)\}/,y={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}};function b(e,t){const n=e.map((e=>{const{start:n,end:o}=y[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${o})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function v(e,t){let n=e.replace(/\n$/,"");const{language:o,magicComments:a,metastring:r}=t;if(r&&g.test(r)){const e=r.match(g).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${r}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,o=f()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(o),code:n}}if(void 0===o)return{lineClassNames:{},code:n};const l=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return b(["js","jsBlock"],t);case"jsx":case"tsx":return b(["js","jsBlock","jsx"],t);case"html":return b(["js","jsBlock","html"],t);case"python":case"py":case"bash":return b(["bash"],t);case"markdown":case"md":return b(["html","jsx","bash"],t);default:return b(Object.keys(y),t)}}(o,a),c=n.split("\n"),s=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),i=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),m=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let p=0;p<c.length;){const e=c[p].match(l);if(!e){p+=1;continue}const t=e.slice(1).find((e=>void 0!==e));i[t]?s[i[t]].range+=`${p},`:m[t]?s[m[t]].start=p:u[t]&&(s[u[t]].range+=`${s[u[t]].start}-${p-1},`),c.splice(p,1)}n=c.join("\n");const d={};return Object.entries(s).forEach((e=>{let[t,{range:n}]=e;f()(n).forEach((e=>{d[e]??=[],d[e].push(t)}))})),{lineClassNames:d,code:n}}const E="codeBlockContainer_Ckt0";function k(e){let{as:t,...n}=e;const a=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[o,a]=e;const r=t[o];r&&"string"==typeof a&&(n[r]=a)})),n}(u());return o.createElement(t,(0,r.Z)({},n,{style:a,className:(0,s.Z)(n.className,E,d.k.common.codeBlock)}))}const N={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function C(e){let{children:t,className:n}=e;return o.createElement(k,{as:"pre",tabIndex:0,className:(0,s.Z)(N.codeBlockStandalone,"thin-scrollbar",n)},o.createElement("code",{className:N.codeBlockLines},t))}var w=n(902);const Z={attributes:!0,characterData:!0,childList:!0,subtree:!0};function T(e,t){const[n,a]=(0,o.useState)(),r=(0,o.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,o.useEffect)((()=>{r()}),[r]),function(e,t,n){void 0===n&&(n=Z);const a=(0,w.zX)(t),r=(0,w.Ql)(n);(0,o.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,r),()=>t.disconnect()}),[e,a,r])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),r())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}const B={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]};var j={Prism:n(7410).Z,theme:B};function _(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function L(){return L=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},L.apply(this,arguments)}var x=/\r\n|\r|\n/,O=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},S=function(e,t){var n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},P=function(e,t){var n=e.plain,o=Object.create(null),a=e.styles.reduce((function(e,n){var o=n.languages,a=n.style;return o&&!o.includes(t)||n.types.forEach((function(t){var n=L({},e[t],a);e[t]=n})),e}),o);return a.root=n,a.plain=L({},n,{backgroundColor:null}),a};function z(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&-1===t.indexOf(o)&&(n[o]=e[o]);return n}const A=function(e){function t(){for(var t=this,n=[],o=arguments.length;o--;)n[o]=arguments[o];e.apply(this,n),_(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?P(e.theme,e.language):void 0;return t.themeDict=n})),_(this,"getLineProps",(function(e){var n=e.key,o=e.className,a=e.style,r=L({},z(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(r.style=l.plain),void 0!==a&&(r.style=void 0!==r.style?L({},r.style,a):a),void 0!==n&&(r.key=n),o&&(r.className+=" "+o),r})),_(this,"getStyleForToken",(function(e){var n=e.types,o=e.empty,a=n.length,r=t.getThemeDict(t.props);if(void 0!==r){if(1===a&&"plain"===n[0])return o?{display:"inline-block"}:void 0;if(1===a&&!o)return r[n[0]];var l=o?{display:"inline-block"}:{},c=n.map((function(e){return r[e]}));return Object.assign.apply(Object,[l].concat(c))}})),_(this,"getTokenProps",(function(e){var n=e.key,o=e.className,a=e.style,r=e.token,l=L({},z(e,["key","className","style","token"]),{className:"token "+r.types.join(" "),children:r.content,style:t.getStyleForToken(r),key:void 0});return void 0!==a&&(l.style=void 0!==l.style?L({},l.style,a):a),void 0!==n&&(l.key=n),o&&(l.className+=" "+o),l})),_(this,"tokenize",(function(e,t,n,o){var a={code:t,grammar:n,language:o,tokens:[]};e.hooks.run("before-tokenize",a);var r=a.tokens=e.tokenize(a.code,a.grammar,a.language);return e.hooks.run("after-tokenize",a),r}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,o=e.code,a=e.children,r=this.getThemeDict(this.props),l=t.languages[n];return a({tokens:function(e){for(var t=[[]],n=[e],o=[0],a=[e.length],r=0,l=0,c=[],s=[c];l>-1;){for(;(r=o[l]++)<a[l];){var i=void 0,m=t[l],u=n[l][r];if("string"==typeof u?(m=l>0?m:["plain"],i=u):(m=S(m,u.type),u.alias&&(m=S(m,u.alias)),i=u.content),"string"==typeof i){var d=i.split(x),p=d.length;c.push({types:m,content:d[0]});for(var f=1;f<p;f++)O(c),s.push(c=[]),c.push({types:m,content:d[f]})}else l++,t.push(m),n.push(i),o.push(0),a.push(i.length)}l--,t.pop(),n.pop(),o.pop(),a.pop()}return O(c),s}(void 0!==l?this.tokenize(t,o,l,n):[o]),className:"prism-code language-"+n,style:void 0!==r?r.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},t}(o.Component),I="codeLine_lJS_",M="codeLineNumber_Tfdd",D="codeLineContent_feaV";function H(e){let{line:t,classNames:n,showLineNumbers:a,getLineProps:l,getTokenProps:c}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const i=l({line:t,className:(0,s.Z)(n,a&&I)}),m=t.map(((e,t)=>o.createElement("span",(0,r.Z)({key:t},c({token:e,key:t})))));return o.createElement("span",i,a?o.createElement(o.Fragment,null,o.createElement("span",{className:M}),o.createElement("span",{className:D},m)):m,o.createElement("br",null))}var V=n(5999);const R={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function $(e){let{code:t,className:n}=e;const[a,r]=(0,o.useState)(!1),l=(0,o.useRef)(void 0),c=(0,o.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;const o=document.createElement("textarea"),a=document.activeElement;o.value=e,o.setAttribute("readonly",""),o.style.contain="strict",o.style.position="absolute",o.style.left="-9999px",o.style.fontSize="12pt";const r=document.getSelection();let l=!1;r.rangeCount>0&&(l=r.getRangeAt(0)),n.append(o),o.select(),o.selectionStart=0,o.selectionEnd=e.length;let c=!1;try{c=document.execCommand("copy")}catch{}o.remove(),l&&(r.removeAllRanges(),r.addRange(l)),a&&a.focus()}(t),r(!0),l.current=window.setTimeout((()=>{r(!1)}),1e3)}),[t]);return(0,o.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),o.createElement("button",{type:"button","aria-label":a?(0,V.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,V.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,V.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,s.Z)("clean-btn",n,R.copyButton,a&&R.copyButtonCopied),onClick:c},o.createElement("span",{className:R.copyButtonIcons,"aria-hidden":"true"},o.createElement("svg",{className:R.copyButtonIcon,viewBox:"0 0 24 24"},o.createElement("path",{d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})),o.createElement("svg",{className:R.copyButtonSuccessIcon,viewBox:"0 0 24 24"},o.createElement("path",{d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))))}const W="wordWrapButtonIcon_Bwma",F="wordWrapButtonEnabled_EoeP";function q(e){let{className:t,onClick:n,isEnabled:a}=e;const r=(0,V.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return o.createElement("button",{type:"button",onClick:n,className:(0,s.Z)("clean-btn",t,a&&F),"aria-label":r,title:r},o.createElement("svg",{className:W,viewBox:"0 0 24 24","aria-hidden":"true"},o.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})))}function G(e){let{children:t,className:n="",metastring:a,title:l,showLineNumbers:c,language:i}=e;const{prism:{defaultLanguage:d,magicComments:p}}=(0,m.L)(),f=i??n.split(" ").find((e=>e.startsWith("language-")))?.replace(/language-/,"")??d;const g=u(),y=function(){const[e,t]=(0,o.useState)(!1),[n,a]=(0,o.useState)(!1),r=(0,o.useRef)(null),l=(0,o.useCallback)((()=>{const n=r.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[r,e]),c=(0,o.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=r.current,n=e>t||r.current.querySelector("code").hasAttribute("style");a(n)}),[r]);return T(r,c),(0,o.useEffect)((()=>{c()}),[e,c]),(0,o.useEffect)((()=>(window.addEventListener("resize",c,{passive:!0}),()=>{window.removeEventListener("resize",c)})),[c]),{codeBlockRef:r,isEnabled:e,isCodeScrollable:n,toggle:l}}(),b=function(e){return e?.match(h)?.groups.title??""}(a)||l,{lineClassNames:E,code:C}=v(t,{metastring:a,language:f,magicComments:p}),w=c??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return o.createElement(k,{as:"div",className:(0,s.Z)(n,f&&!n.includes(`language-${f}`)&&`language-${f}`)},b&&o.createElement("div",{className:N.codeBlockTitle},b),o.createElement("div",{className:N.codeBlockContent},o.createElement(A,(0,r.Z)({},j,{theme:g,code:C,language:f??"text"}),(e=>{let{className:t,tokens:n,getLineProps:a,getTokenProps:r}=e;return o.createElement("pre",{tabIndex:0,ref:y.codeBlockRef,className:(0,s.Z)(t,N.codeBlock,"thin-scrollbar")},o.createElement("code",{className:(0,s.Z)(N.codeBlockLines,w&&N.codeBlockLinesWithNumbering)},n.map(((e,t)=>o.createElement(H,{key:t,line:e,getLineProps:a,getTokenProps:r,classNames:E[t],showLineNumbers:w})))))})),o.createElement("div",{className:N.buttonGroup},(y.isEnabled||y.isCodeScrollable)&&o.createElement(q,{className:N.codeButton,onClick:()=>y.toggle(),isEnabled:y.isEnabled}),o.createElement($,{className:N.codeButton,code:C}))))}function U(e){let{children:t,...n}=e;const a=(0,c.Z)(),l=function(e){return o.Children.toArray(e).some((e=>(0,o.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),s="string"==typeof l?G:C;return o.createElement(s,(0,r.Z)({key:String(a)},n),l)}var Q=n(9960);var X=n(6043);const Y="details_lb9f",J="isBrowser_bmU9",K="collapsibleContent_i85q";function ee(e){return!!e&&("SUMMARY"===e.tagName||ee(e.parentElement))}function te(e,t){return!!e&&(e===t||te(e.parentElement,t))}function ne(e){let{summary:t,children:n,...a}=e;const l=(0,c.Z)(),i=(0,o.useRef)(null),{collapsed:m,setCollapsed:u}=(0,X.u)({initialState:!a.open}),[d,p]=(0,o.useState)(a.open);return o.createElement("details",(0,r.Z)({},a,{ref:i,open:d,"data-collapsed":m,className:(0,s.Z)(Y,l&&J,a.className),onMouseDown:e=>{ee(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;ee(t)&&te(t,i.current)&&(e.preventDefault(),m?(u(!1),p(!0)):u(!0))}}),t??o.createElement("summary",null,"Details"),o.createElement(X.z,{lazy:!1,collapsed:m,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{u(e),p(!e)}},o.createElement("div",{className:K},n)))}const oe="details_b_Ee";function ae(e){let{...t}=e;return o.createElement(ne,(0,r.Z)({},t,{className:(0,s.Z)("alert alert--info",oe,t.className)}))}var re=n(2503);function le(e){return o.createElement(re.Z,e)}const ce="containsTaskList_mC6p";const se="img_ev3q";const ie="admonition_LlT9",me="admonitionHeading_tbUL",ue="admonitionIcon_kALy",de="admonitionContent_S0QG";const pe={note:{infimaClassName:"secondary",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:o.createElement(V.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:o.createElement(V.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 12 16"},o.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:o.createElement(V.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 14 16"},o.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:o.createElement(V.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return o.createElement("svg",{viewBox:"0 0 16 16"},o.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:o.createElement(V.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},fe={secondary:"note",important:"info",success:"tip",warning:"danger"};function he(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=o.Children.toArray(e),n=t.find((e=>o.isValidElement(e)&&"mdxAdmonitionTitle"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return{mdxAdmonitionTitle:n,rest:a}}(e.children);return{...e,title:e.title??t,children:n}}const ge={head:function(e){const t=o.Children.map(e.children,(e=>o.isValidElement(e)?function(e){if(e.props?.mdxType&&e.props.originalType){const{mdxType:t,originalType:n,...a}=e.props;return o.createElement(e.props.originalType,a)}return e}(e):e));return o.createElement(l.Z,e,t)},code:function(e){const t=["a","abbr","b","br","button","cite","code","del","dfn","em","i","img","input","ins","kbd","label","object","output","q","ruby","s","small","span","strong","sub","sup","time","u","var","wbr"];return o.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")||(0,o.isValidElement)(e)&&t.includes(e.props?.mdxType)))?o.createElement("code",e):o.createElement(U,e)},a:function(e){return o.createElement(Q.Z,e)},pre:function(e){return o.createElement(U,(0,o.isValidElement)(e.children)&&"code"===e.children.props?.originalType?e.children.props:{...e})},details:function(e){const t=o.Children.toArray(e.children),n=t.find((e=>o.isValidElement(e)&&"summary"===e.props?.mdxType)),a=o.createElement(o.Fragment,null,t.filter((e=>e!==n)));return o.createElement(ae,(0,r.Z)({},e,{summary:n}),a)},ul:function(e){return o.createElement("ul",(0,r.Z)({},e,{className:(t=e.className,(0,s.Z)(t,t?.includes("contains-task-list")&&ce))}));var t},img:function(e){return o.createElement("img",(0,r.Z)({loading:"lazy"},e,{className:(t=e.className,(0,s.Z)(t,se))}));var t},h1:e=>o.createElement(le,(0,r.Z)({as:"h1"},e)),h2:e=>o.createElement(le,(0,r.Z)({as:"h2"},e)),h3:e=>o.createElement(le,(0,r.Z)({as:"h3"},e)),h4:e=>o.createElement(le,(0,r.Z)({as:"h4"},e)),h5:e=>o.createElement(le,(0,r.Z)({as:"h5"},e)),h6:e=>o.createElement(le,(0,r.Z)({as:"h6"},e)),admonition:function(e){const{children:t,type:n,title:a,icon:r}=he(e),l=function(e){const t=fe[e]??e,n=pe[t];return n||(console.warn(`No admonition config found for admonition type "${t}". Using Info as fallback.`),pe.info)}(n),c=a??l.label,{iconComponent:i}=l,m=r??o.createElement(i,null);return o.createElement("div",{className:(0,s.Z)(d.k.common.admonition,d.k.common.admonitionType(e.type),"alert",`alert--${l.infimaClassName}`,ie)},o.createElement("div",{className:me},o.createElement("span",{className:ue},m),c),o.createElement("div",{className:de},t))},mermaid:n(1875).Z};function ye(e){let{children:t}=e;return o.createElement(a.Zo,{components:ge},t)}},2244:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l});var o=n(7294),a=n(6010),r=n(9960);function l(e){const{permalink:t,title:n,subLabel:l,isNext:c}=e;return o.createElement(r.Z,{className:(0,a.Z)("pagination-nav__link",c?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},l&&o.createElement("div",{className:"pagination-nav__sublabel"},l),o.createElement("div",{className:"pagination-nav__label"},n))}},3008:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var o=n(7294),a=n(6010),r=n(9960);const l="tag_zVej",c="tagRegular_sFm0",s="tagWithCount_h2kH";function i(e){let{permalink:t,label:n,count:i}=e;return o.createElement(r.Z,{href:t,className:(0,a.Z)(l,i?s:c)},n,i&&o.createElement("span",null,i))}},1526:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var o=n(7294),a=n(6010),r=n(5999),l=n(3008);const c="tags_jXut",s="tag_QGVx";function i(e){let{tags:t}=e;return o.createElement(o.Fragment,null,o.createElement("b",null,o.createElement(r.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),o.createElement("ul",{className:(0,a.Z)(c,"padding--none","margin-left--sm")},t.map((e=>{let{label:t,permalink:n}=e;return o.createElement("li",{key:n,className:s},o.createElement(l.Z,{label:t,permalink:n}))}))))}},7594:(e,t)=>{function n(e){let t,n=[];for(let o of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(o))n.push(parseInt(o,10));else if(t=o.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,o,a,r]=t;if(o&&r){o=parseInt(o),r=parseInt(r);const e=o<r?1:-1;"-"!==a&&".."!==a&&"\u2025"!==a||(r+=e);for(let t=o;t!==r;t+=e)n.push(t)}}return n}t.default=n,e.exports=n}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/73f84a4a.4c420f96.js b/pr-preview/pr-192/assets/js/73f84a4a.4c420f96.js deleted file mode 100644 index c4a14e2ee..000000000 --- a/pr-preview/pr-192/assets/js/73f84a4a.4c420f96.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9492],{9026:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-192/blog/tags/celestia","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"Blog","blogTitle":"Blog"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/7aa79d9e.bfc0122e.js b/pr-preview/pr-192/assets/js/7aa79d9e.bfc0122e.js deleted file mode 100644 index c15bb8a74..000000000 --- a/pr-preview/pr-192/assets/js/7aa79d9e.bfc0122e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5331],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>d});var l=o(7294);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function i(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,l)}return o}function r(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?i(Object(o),!0).forEach((function(t){n(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):i(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}function a(e,t){if(null==e)return{};var o,l,n=function(e,t){if(null==e)return{};var o,l,n={},i=Object.keys(e);for(l=0;l<i.length;l++)o=i[l],t.indexOf(o)>=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(l=0;l<i.length;l++)o=i[l],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o])}return n}var s=l.createContext({}),c=function(e){var t=l.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},u=function(e){var t=c(e.components);return l.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var o=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),p=c(o),h=n,d=p["".concat(s,".").concat(h)]||p[h]||m[h]||i;return o?l.createElement(d,r(r({ref:t},u),{},{components:o})):l.createElement(d,r({ref:t},u))}));function d(e,t){var o=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=o.length,r=new Array(i);r[0]=h;var a={};for(var s in t)hasOwnProperty.call(t,s)&&(a[s]=t[s]);a.originalType=e,a[p]="string"==typeof e?e:n,r[1]=a;for(var c=2;c<i;c++)r[c]=o[c];return l.createElement.apply(null,r)}return l.createElement.apply(null,o)}h.displayName="MDXCreateElement"},1420:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var l=o(7462),n=(o(7294),o(3905));const i={slug:"lets-roll-community-call",title:"Let's Roll - Rollkit's community call",authors:["AlCJoseph"],tags:["Rollkit"],description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."},r=void 0,a={permalink:"/pr-preview/pr-192/blog/lets-roll-community-call",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-03-08-lets-roll.mdx",source:"@site/blog/2023-03-08-lets-roll.mdx",title:"Let's Roll - Rollkit's community call",description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.",date:"2023-03-08T00:00:00.000Z",formattedDate:"March 8, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"}],readingTime:3.245,hasTruncateMarker:!1,authors:[{name:"Joseph Al-Chami",url:"https://github.com/AlCJoseph",imageURL:"https://github.com/AlCJoseph.png",key:"AlCJoseph"}],frontMatter:{slug:"lets-roll-community-call",title:"Let's Roll - Rollkit's community call",authors:["AlCJoseph"],tags:["Rollkit"],description:"Rollkit is kicking off its community call, Let's Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."},nextItem:{title:"Sovereign rollups on Bitcoin with Rollkit",permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},s={authorsImageUrls:[void 0]},c=[{value:"TL;DR",id:"tldr",level:2},{value:"Just merge it",id:"just-merge-it",level:2},{value:"What is Let\u2019s Roll?",id:"what-is-lets-roll",level:2},{value:"Conclusion",id:"conclusion",level:2}],u={toc:c};function p(e){let{components:t,...i}=e;return(0,n.kt)("wrapper",(0,l.Z)({},u,i,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,(0,n.kt)("img",{alt:"Rollkit blog cover",src:o(5756).Z,width:"3000",height:"1500"})),(0,n.kt)("p",null,"Last Sunday, we released the first ",(0,n.kt)("a",{parentName:"p",href:"https://rollkit.dev/blog/sovereign-rollups-on-bitcoin/"},"research implementation")," that allows Rollkit rollups to use Bitcoin for data availability. "),(0,n.kt)("p",null,(0,n.kt)("a",{parentName:"p",href:"https://twitter.com/RollkitDev/status/1632438374513676288"},"This announcement")," has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They\u2019re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements."),(0,n.kt)("p",null,"We believe that there\u2019s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks."),(0,n.kt)("p",null,"That\u2019s why we\u2019re happy to announce that we\u2019re launching a Rollkit\u2019s community call: Let\u2019s Roll."),(0,n.kt)("h2",{id:"tldr"},"TL;DR"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Rollkit is launching its community call, Let\u2019s Roll. You can subscribe to the community calendar ",(0,n.kt)("a",{parentName:"p",href:"https://calendar.google.com/calendar/u/0/embed?src=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com&ctz=America/Toronto"},"here"))),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"The first meeting is scheduled on ",(0,n.kt)("a",{parentName:"p",href:"https://us06web.zoom.us/j/83308619122"},"Zoom")," for March 21, 2023, 6pm CET(12pm EST, 9am PST).")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Builders using Rollkit can now present their projects at Let\u2019s Roll. Reach out to us on ",(0,n.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram")," "))),(0,n.kt)("h2",{id:"just-merge-it"},"Just merge it"),(0,n.kt)("p",null,"Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good. "),(0,n.kt)("p",null,"However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit\u2019s development."),(0,n.kt)("p",null,"By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community. "),(0,n.kt)("p",null,"One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use."),(0,n.kt)("p",null,"Our promise, as core contributors, is to do our best to make \u201cjust merge it\u201d a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated. "),(0,n.kt)("p",null,"That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit."),(0,n.kt)("h2",{id:"what-is-lets-roll"},"What is Let\u2019s Roll?"),(0,n.kt)("p",null,"Let's Roll is a dynamic community-focused meeting that brings together all Rollkit\u2019s contributors to drive the innovation and development of Rollkit."),(0,n.kt)("p",null,"This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects."),(0,n.kt)("p",null,"Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently."),(0,n.kt)("p",null,"The meeting will be hosted on ",(0,n.kt)("a",{parentName:"p",href:"https://us06web.zoom.us/j/83308619122"},"Zoom"),". Subscribe to the following ",(0,n.kt)("a",{parentName:"p",href:"https://calendar.google.com/calendar/u/0/r?cid=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com"},"Google calendar")," so that you can be notified of future community calls."),(0,n.kt)("h2",{id:"conclusion"},"Conclusion"),(0,n.kt)("p",null,"Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework.\nWith demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project."),(0,n.kt)("p",null,"We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together."),(0,n.kt)("p",null,"So, join us, roll with us, and let's shape the future of rollup frameworks together."))}p.isMDXComponent=!0},5756:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/lets-roll-a8b580bec3f0ea690483252f65daa0c1.jpg"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/7d4011c1.c36b3498.js b/pr-preview/pr-192/assets/js/7d4011c1.c36b3498.js deleted file mode 100644 index 0e8a69c5a..000000000 --- a/pr-preview/pr-192/assets/js/7d4011c1.c36b3498.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[2844],{3905:(t,e,i)=>{i.d(e,{Zo:()=>p,kt:()=>m});var o=i(7294);function a(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function n(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,o)}return i}function l(t){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{};e%2?n(Object(i),!0).forEach((function(e){a(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):n(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function r(t,e){if(null==t)return{};var i,o,a=function(t,e){if(null==t)return{};var i,o,a={},n=Object.keys(t);for(o=0;o<n.length;o++)i=n[o],e.indexOf(i)>=0||(a[i]=t[i]);return a}(t,e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);for(o=0;o<n.length;o++)i=n[o],e.indexOf(i)>=0||Object.prototype.propertyIsEnumerable.call(t,i)&&(a[i]=t[i])}return a}var s=o.createContext({}),c=function(t){var e=o.useContext(s),i=e;return t&&(i="function"==typeof t?t(e):l(l({},e),t)),i},p=function(t){var e=c(t.components);return o.createElement(s.Provider,{value:e},t.children)},d="mdxType",u={inlineCode:"code",wrapper:function(t){var e=t.children;return o.createElement(o.Fragment,{},e)}},h=o.forwardRef((function(t,e){var i=t.components,a=t.mdxType,n=t.originalType,s=t.parentName,p=r(t,["components","mdxType","originalType","parentName"]),d=c(i),h=a,m=d["".concat(s,".").concat(h)]||d[h]||u[h]||n;return i?o.createElement(m,l(l({ref:e},p),{},{components:i})):o.createElement(m,l({ref:e},p))}));function m(t,e){var i=arguments,a=e&&e.mdxType;if("string"==typeof t||a){var n=i.length,l=new Array(n);l[0]=h;var r={};for(var s in e)hasOwnProperty.call(e,s)&&(r[s]=e[s]);r.originalType=t,r[d]="string"==typeof t?t:a,l[1]=r;for(var c=2;c<n;c++)l[c]=i[c];return o.createElement.apply(null,l)}return o.createElement.apply(null,i)}h.displayName="MDXCreateElement"},8672:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>n,metadata:()=>r,toc:()=>c});var o=i(7462),a=(i(7294),i(3905));const n={slug:"sovereign-rollups-on-bitcoin",title:"Sovereign rollups on Bitcoin with Rollkit",authors:["rollkit"],tags:["Rollkit","Bitcoin"],description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it."},l=void 0,r={permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx",source:"@site/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx",title:"Sovereign rollups on Bitcoin with Rollkit",description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it.",date:"2023-03-05T00:00:00.000Z",formattedDate:"March 5, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"},{label:"Bitcoin",permalink:"/pr-preview/pr-192/blog/tags/bitcoin"}],readingTime:4.32,hasTruncateMarker:!1,authors:[{name:"Rollkit",url:"https://github.com/rollkit",imageURL:"https://github.com/rollkit.png",key:"rollkit"}],frontMatter:{slug:"sovereign-rollups-on-bitcoin",title:"Sovereign rollups on Bitcoin with Rollkit",authors:["rollkit"],tags:["Rollkit","Bitcoin"],description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it."},prevItem:{title:"Let's Roll - Rollkit's community call",permalink:"/pr-preview/pr-192/blog/lets-roll-community-call"},nextItem:{title:"Introducing Rollkit: a modular rollup framework",permalink:"/pr-preview/pr-192/blog/introducing-rollkit"}},s={authorsImageUrls:[void 0]},c=[{value:"Tl;dr",id:"tldr",level:2},{value:"Posting data on Bitcoin with Taproot",id:"posting-data-on-bitcoin-with-taproot",level:2},{value:"Integrating Bitcoin as a data availability layer into Rollkit",id:"integrating-bitcoin-as-a-data-availability-layer-into-rollkit",level:2},{value:"How Rollkit posts data to Bitcoin",id:"how-rollkit-posts-data-to-bitcoin",level:2},{value:"EVM on Bitcoin demo",id:"evm-on-bitcoin-demo",level:2},{value:"Conclusion",id:"conclusion",level:2}],p={toc:c};function d(t){let{components:e,...n}=t;return(0,a.kt)("wrapper",(0,o.Z)({},p,n,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin",src:i(2223).Z,width:"3000",height:"1500"})),(0,a.kt)("p",null,"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability."),(0,a.kt)("p",null,"Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin\u2019s data availability guarantees and re-org resistance. With the new integration it is now possible to run the ",(0,a.kt)("a",{parentName:"p",href:"/docs/tutorials/bitcoin"},"EVM on Bitcoin as a Rollkit sovereign rollup"),". Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget."),(0,a.kt)("h2",{id:"tldr"},"Tl;dr"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit\u2019s new early research integration."),(0,a.kt)("li",{parentName:"ul"},"Follow along with a ",(0,a.kt)("a",{parentName:"li",href:"#evm-on-bitcoin-demo"},"demo")," of the EVM running on Bitcoin as a sovereign Rollkit rollup."),(0,a.kt)("li",{parentName:"ul"},"The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.")),(0,a.kt)("h2",{id:"posting-data-on-bitcoin-with-taproot"},"Posting data on Bitcoin with Taproot"),(0,a.kt)("p",null,"On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with ",(0,a.kt)("a",{parentName:"p",href:"https://ordinals.com/"},"Ordinals"),", a project that implements NFTs on Bitcoin by publishing the image data on-chain."),(0,a.kt)("p",null,"Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain."),(0,a.kt)("p",null,"Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has ",(0,a.kt)("a",{parentName:"p",href:"https://dune.com/dataalways/ordinals"},"kicked off"),". Eric Wall found that at the time of ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/ercwl/status/1619671451417862145"},"his tweet"),", posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer."),(0,a.kt)("h2",{id:"integrating-bitcoin-as-a-data-availability-layer-into-rollkit"},"Integrating Bitcoin as a data availability layer into Rollkit"),(0,a.kt)("p",null,"Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin-rollup",src:i(2626).Z,width:"3000",height:"2708"})),(0,a.kt)("h2",{id:"how-rollkit-posts-data-to-bitcoin"},"How Rollkit posts data to Bitcoin"),(0,a.kt)("p",null,"To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/bitcoin-da"},"a Go package called ",(0,a.kt)("inlineCode",{parentName:"a"},"bitcoin-da"))," that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit-btc/blob/main/spec.md"},"the specs"),". The package can be re-used by any project that wants to read or write data on Bitcoin."),(0,a.kt)("p",null,"Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the ",(0,a.kt)("inlineCode",{parentName:"p"},"DataAvailabilityLayerClient")," interface which defines the behavior of the data availability client, and the ",(0,a.kt)("inlineCode",{parentName:"p"},"BlockRetriever")," interface which defines how blocks can be synced. These interfaces live in the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/da"},"da package"),". The most important methods in these interfaces are ",(0,a.kt)("inlineCode",{parentName:"p"},"SubmitBlock")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"RetrieveBlock")," for reading and writing the blocks."),(0,a.kt)("p",null,"After implementing the Taproot reader/writer interface for Bitcoin (",(0,a.kt)("inlineCode",{parentName:"p"},"bitcoin-da"),"), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the ",(0,a.kt)("inlineCode",{parentName:"p"},"SubmitBlock")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"RetrieveBlocks")," functions for Rollkit to call the ",(0,a.kt)("inlineCode",{parentName:"p"},"Read")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"Write")," methods in ",(0,a.kt)("inlineCode",{parentName:"p"},"bitcoin-da"),"."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin-rollup-2",src:i(2622).Z,width:"3000",height:"1415"})),(0,a.kt)("h2",{id:"evm-on-bitcoin-demo"},"EVM on Bitcoin demo"),(0,a.kt)("p",null,"Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo."),(0,a.kt)("div",{class:"youtube-wrapper"},(0,a.kt)("iframe",{class:"youtube-video",title:"Rollkit: Ethermint + Bitcoin DA demo",src:"https://www.youtube.com/embed/qBKFEctzgT0",allowfullscreen:!0})),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. ",(0,a.kt)("a",{parentName:"p",href:"https://blog.celestia.org/sovereign-rollup-chains/"},"Sovereign rollups")," fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin."),(0,a.kt)("p",null,"Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions ",(0,a.kt)("a",{parentName:"p",href:"/docs/tutorials/bitcoin"},"here"),". Keep in mind that the integration is an early research implementation and it is not yet production-ready!"),(0,a.kt)("p",null,"Modularism, not maximalism."))}d.isMDXComponent=!0},2626:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png"},2622:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-2-e97ee76fdc66279cd58e7e27177fcdb0.png"},2223:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-7bcecada0c85b79bf2b58ed20980d43c.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/80930d5b.dd96b7fe.js b/pr-preview/pr-192/assets/js/80930d5b.dd96b7fe.js deleted file mode 100644 index 4a8899795..000000000 --- a/pr-preview/pr-192/assets/js/80930d5b.dd96b7fe.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8347],{2561:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"lets-roll-community-call","metadata":{"permalink":"/pr-preview/pr-192/blog/lets-roll-community-call","editUrl":"https://github.com/rollkit/docs/tree/main/blog/2023-03-08-lets-roll.mdx","source":"@site/blog/2023-03-08-lets-roll.mdx","title":"Let\'s Roll - Rollkit\'s community call","description":"Rollkit is kicking off its community call, Let\'s Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what\'s possible with Rollkit.","date":"2023-03-08T00:00:00.000Z","formattedDate":"March 8, 2023","tags":[{"label":"Rollkit","permalink":"/pr-preview/pr-192/blog/tags/rollkit"}],"readingTime":3.245,"hasTruncateMarker":false,"authors":[{"name":"Joseph Al-Chami","url":"https://github.com/AlCJoseph","imageURL":"https://github.com/AlCJoseph.png","key":"AlCJoseph"}],"frontMatter":{"slug":"lets-roll-community-call","title":"Let\'s Roll - Rollkit\'s community call","authors":["AlCJoseph"],"tags":["Rollkit"],"description":"Rollkit is kicking off its community call, Let\'s Roll, to bring together community members to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what\'s possible with Rollkit."},"nextItem":{"title":"Sovereign rollups on Bitcoin with Rollkit","permalink":"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},"content":"![Rollkit blog cover](../static/img/lets-roll/lets-roll.jpg)\\n\\nLast Sunday, we released the first [research implementation](https://rollkit.dev/blog/sovereign-rollups-on-bitcoin/) that allows Rollkit rollups to use Bitcoin for data availability. \\n\\n[This announcement](https://twitter.com/RollkitDev/status/1632438374513676288) has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They\u2019re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.\\n \\nWe believe that there\u2019s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.\\n\\nThat\u2019s why we\u2019re happy to announce that we\u2019re launching a Rollkit\u2019s community call: Let\u2019s Roll.\\n\\n## TL;DR\\n\\n* Rollkit is launching its community call, Let\u2019s Roll. You can subscribe to the community calendar [here](https://calendar.google.com/calendar/u/0/embed?src=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com&ctz=America/Toronto)\\n\\n* The first meeting is scheduled on [Zoom](https://us06web.zoom.us/j/83308619122) for March 21, 2023, 6pm CET(12pm EST, 9am PST).\\n\\n* Builders using Rollkit can now present their projects at Let\u2019s Roll. Reach out to us on [Telegram](https://t.me/rollkit) \\n\\n## Just merge it\\n\\nRollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good. \\n\\nHowever, Rollkit\'s true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit\u2019s development.\\n\\nBy contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community. \\n\\nOne framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.\\n\\nOur promise, as core contributors, is to do our best to make \u201cjust merge it\u201d a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated. \\n\\nThat\'s why we believe it\'s time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what\'s possible with Rollkit.\\n\\n## What is Let\u2019s Roll?\\n\\nLet\'s Roll is a dynamic community-focused meeting that brings together all Rollkit\u2019s contributors to drive the innovation and development of Rollkit.\\n\\nThis meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit\'s contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.\\n\\nBuilding open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.\\n\\nThe meeting will be hosted on [Zoom](https://us06web.zoom.us/j/83308619122). Subscribe to the following [Google calendar](https://calendar.google.com/calendar/u/0/r?cid=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com) so that you can be notified of future community calls.\\n\\n## Conclusion\\n\\nLet\'s Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework.\\nWith demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let\'s Roll is an opportunity to stay informed and engaged with the project.\\n\\nWe invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.\\n\\nSo, join us, roll with us, and let\'s shape the future of rollup frameworks together."},{"id":"sovereign-rollups-on-bitcoin","metadata":{"permalink":"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin","editUrl":"https://github.com/rollkit/docs/tree/main/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx","source":"@site/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx","title":"Sovereign rollups on Bitcoin with Rollkit","description":"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it.","date":"2023-03-05T00:00:00.000Z","formattedDate":"March 5, 2023","tags":[{"label":"Rollkit","permalink":"/pr-preview/pr-192/blog/tags/rollkit"},{"label":"Bitcoin","permalink":"/pr-preview/pr-192/blog/tags/bitcoin"}],"readingTime":4.32,"hasTruncateMarker":false,"authors":[{"name":"Rollkit","url":"https://github.com/rollkit","imageURL":"https://github.com/rollkit.png","key":"rollkit"}],"frontMatter":{"slug":"sovereign-rollups-on-bitcoin","title":"Sovereign rollups on Bitcoin with Rollkit","authors":["rollkit"],"tags":["Rollkit","Bitcoin"],"description":"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it."},"prevItem":{"title":"Let\'s Roll - Rollkit\'s community call","permalink":"/pr-preview/pr-192/blog/lets-roll-community-call"},"nextItem":{"title":"Introducing Rollkit: a modular rollup framework","permalink":"/pr-preview/pr-192/blog/introducing-rollkit"}},"content":"![rollkit-bitcoin](../static/img/bitcoin-rollkit/rollkit-bitcoin.png)\\n\\nLast week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.\\n\\nRollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin\u2019s data availability guarantees and re-org resistance. With the new integration it is now possible to run the [EVM on Bitcoin as a Rollkit sovereign rollup](/docs/tutorials/bitcoin). Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.\\n\\n## Tl;dr\\n\\n- Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit\u2019s new early research integration.\\n- Follow along with a [demo](#evm-on-bitcoin-demo) of the EVM running on Bitcoin as a sovereign Rollkit rollup.\\n- The implementation was possible due to Bitcoin\'s Taproot upgrade and Ordinals\' usage of Bitcoin for publishing arbitrary data.\\n\\n## Posting data on Bitcoin with Taproot\\n\\nOn Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with [Ordinals](https://ordinals.com/), a project that implements NFTs on Bitcoin by publishing the image data on-chain.\\n\\nBitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin\'s Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.\\n\\nSince then, the usage of Ordinals for NFT inscriptions and Taproot utilization has [kicked off](https://dune.com/dataalways/ordinals). Eric Wall found that at the time of [his tweet](https://twitter.com/ercwl/status/1619671451417862145), posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.\\n\\n## Integrating Bitcoin as a data availability layer into Rollkit\\n\\nRollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.\\n\\n![rollkit-bitcoin-rollup](../static/img/bitcoin-rollkit/rollkit-bitcoin-1.png)\\n\\n## How Rollkit posts data to Bitcoin\\n\\nTo write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented [a Go package called `bitcoin-da`](https://github.com/rollkit/bitcoin-da) that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see [the specs](https://github.com/rollkit/rollkit-btc/blob/main/spec.md). The package can be re-used by any project that wants to read or write data on Bitcoin.\\n\\nRollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the `DataAvailabilityLayerClient` interface which defines the behavior of the data availability client, and the `BlockRetriever` interface which defines how blocks can be synced. These interfaces live in the [da package](https://github.com/rollkit/rollkit/tree/main/da). The most important methods in these interfaces are `SubmitBlock` and `RetrieveBlock` for reading and writing the blocks.\\n\\nAfter implementing the Taproot reader/writer interface for Bitcoin (`bitcoin-da`), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the `SubmitBlock` and `RetrieveBlocks` functions for Rollkit to call the `Read` and `Write` methods in `bitcoin-da`.\\n\\n![rollkit-bitcoin-rollup-2](../static/img/bitcoin-rollkit/rollkit-bitcoin-2.png)\\n\\n## EVM on Bitcoin demo\\n\\nRollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.\\n\\n<div class=\\"youtube-wrapper\\">\\n <iframe\\n class=\\"youtube-video\\"\\n title=\\"Rollkit: Ethermint + Bitcoin DA demo\\"\\n src=\\"https://www.youtube.com/embed/qBKFEctzgT0\\"\\n allowfullscreen\\n >\\n </iframe>\\n</div>\\n\\n## Conclusion\\n\\nAs we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. [Sovereign rollups](https://blog.celestia.org/sovereign-rollup-chains/) fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.\\n\\nOur goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions [here](/docs/tutorials/bitcoin). Keep in mind that the integration is an early research implementation and it is not yet production-ready!\\n\\nModularism, not maximalism."},{"id":"introducing-rollkit","metadata":{"permalink":"/pr-preview/pr-192/blog/introducing-rollkit","editUrl":"https://github.com/rollkit/docs/tree/main/blog/2023-02-21-introducing-rollkit.mdx","source":"@site/blog/2023-02-21-introducing-rollkit.mdx","title":"Introducing Rollkit: a modular rollup framework","description":"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation","date":"2023-02-21T00:00:00.000Z","formattedDate":"February 21, 2023","tags":[{"label":"Rollkit","permalink":"/pr-preview/pr-192/blog/tags/rollkit"},{"label":"Celestia","permalink":"/pr-preview/pr-192/blog/tags/celestia"}],"readingTime":5.985,"hasTruncateMarker":false,"authors":[{"name":"Joseph Al-Chami","url":"https://github.com/AlCJoseph","imageURL":"https://github.com/AlCJoseph.png","key":"AlCJoseph"},{"name":"Alex Beckett","url":"https://github.com/alex-beckett","imageURL":"https://github.com/alex-beckett.png","key":"alex-beckett"}],"frontMatter":{"slug":"introducing-rollkit","title":"Introducing Rollkit: a modular rollup framework","authors":["AlCJoseph","alex-beckett"],"tags":["Rollkit","Celestia"],"description":"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation"},"prevItem":{"title":"Sovereign rollups on Bitcoin with Rollkit","permalink":"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},"content":"_The original version of this blog post can be found on the [Celestia blog](https://blog.celestia.org/introducing-rollkit-a-modular-rollup-framework/)._\\n\\n![Rollkit blog cover](../static/img/introducing-rollkit/rollkit-blog-cover.png)\\n\\nToday, we\u2019re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.\\n\\nRollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any [ABCI](https://github.com/informalsystems/tendermint/tree/main/abci)-compatible blockchain app, including Cosmos chains.\\n\\nIn development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at [rollkit.dev](/).\\n\\n## Tl;dr:\\n\\n- You can now [build with Rollkit](/) on Celestia\u2019s Mocha testnet. Check out the [docs](/)\\n- You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit\u2019s modular framework\\n- Join our Rollkit developer calls that begin in April to help guide its development\\n\\n## Deploying a new chain is hard\\n\\nDeploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain\'s execution environment. This limits your application\'s scalability and flexibility.\\n\\nFor that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.\\n\\nIn order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.\\n\\n## Freedom to deploy\\n\\nRollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.\\n\\n![Rollkit comparison table](../static/img/introducing-rollkit/comparison-table.png)\\n\\nRollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.\\n\\nWith Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don\u2019t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.\\n\\n## Vision for Rollkit\\n\\nIn the spirit of modularity, Rollkit\u2019s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.\\n\\nIn a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit\u2019s customizable stack will enable developers to bring their products to market faster and with more flexibility.\\n\\n![Rollkit lego image](../static/img/introducing-rollkit/rollkit-lego.png)\\n\\n### Execution environments\\n\\nRollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.\\n\\n### Sequencers\\n\\nRollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.\\n\\n### Proof schemes\\n\\nRollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.\\n\\n### Rollup types\\n\\nRollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.\\n\\nRollkit is in an early stage of development and many features remain to be built to reach this vision. In its [current state](/docs/rollkit-stack), Rollkit rollups are [sovereign rollups](https://blog.celestia.org/sovereign-rollup-chains) with single sequencers, with support for a pessimistic mode and a [work-in-progress optimistic mode](https://github.com/rollkit/rollkit/blob/manav/state_fraud_proofs_adr/docs/lazy-adr/adr-009-state-fraud-proofs.md). [Integration tutorials](/docs/category/tutorials) are ready and available with Cosmos SDK, Ethermint, and CosmWasm.\\n\\nWe invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action. \\n\\n## Rollkit is neutral\\n\\nCelestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.\\n\\nSince 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes [Eclipse](https://twitter.com/EclipseFND) (Solana VM rollups), [Dymension](https://twitter.com/dymensionXYZ) (settled Cosmos rollups), [Sovereign Labs](https://twitter.com/sovereign_labs) (sovereign ZK rollups), and [Optimism](https://twitter.com/optimismFND) (EVM rollups).\\n\\nTo ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.\\n\\nThis also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the [data availability interface](https://github.com/rollkit/rollkit/blob/567b9f500db8055289365ea63450cefe4b135077/da/da.go#L60).\\n\\nThe Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.\\n\\nSpinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.\\n\\nWe believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it\u2019s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.\\n\\n## Next steps\\n\\nMoving towards a community-led project means increased visibility, transparency and inclusivity. That\u2019s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit. \\n\\nLearn more about how Rollkit works [on the new Rollkit website](/) (you\'re already on it!). And don\u2019t forget to check out the [Rollkit repo](https://github.com/rollkit) too.\\n\\nLet\u2019s build modular together."}]}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/814f3328.9d5272cf.js b/pr-preview/pr-192/assets/js/814f3328.9d5272cf.js deleted file mode 100644 index a4aad5670..000000000 --- a/pr-preview/pr-192/assets/js/814f3328.9d5272cf.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[2535],{5641:l=>{l.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"Let\'s Roll - Rollkit\'s community call","permalink":"/pr-preview/pr-192/blog/lets-roll-community-call"},{"title":"Sovereign rollups on Bitcoin with Rollkit","permalink":"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"},{"title":"Introducing Rollkit: a modular rollup framework","permalink":"/pr-preview/pr-192/blog/introducing-rollkit"}]}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/84d3f767.6e19ef29.js b/pr-preview/pr-192/assets/js/84d3f767.6e19ef29.js deleted file mode 100644 index fe03d4529..000000000 --- a/pr-preview/pr-192/assets/js/84d3f767.6e19ef29.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[863],{3905:(e,t,o)=>{o.d(t,{Zo:()=>u,kt:()=>m});var l=o(7294);function i(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function a(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,l)}return o}function r(e){for(var t=1;t<arguments.length;t++){var o=null!=arguments[t]?arguments[t]:{};t%2?a(Object(o),!0).forEach((function(t){i(e,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):a(Object(o)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))}))}return e}function n(e,t){if(null==e)return{};var o,l,i=function(e,t){if(null==e)return{};var o,l,i={},a=Object.keys(e);for(l=0;l<a.length;l++)o=a[l],t.indexOf(o)>=0||(i[o]=e[o]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(l=0;l<a.length;l++)o=a[l],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(i[o]=e[o])}return i}var s=l.createContext({}),p=function(e){var t=l.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):r(r({},t),e)),o},u=function(e){var t=p(e.components);return l.createElement(s.Provider,{value:t},e.children)},c="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},h=l.forwardRef((function(e,t){var o=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=n(e,["components","mdxType","originalType","parentName"]),c=p(o),h=i,m=c["".concat(s,".").concat(h)]||c[h]||d[h]||a;return o?l.createElement(m,r(r({ref:t},u),{},{components:o})):l.createElement(m,r({ref:t},u))}));function m(e,t){var o=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=o.length,r=new Array(a);r[0]=h;var n={};for(var s in t)hasOwnProperty.call(t,s)&&(n[s]=t[s]);n.originalType=e,n[c]="string"==typeof e?e:i,r[1]=n;for(var p=2;p<a;p++)r[p]=o[p];return l.createElement.apply(null,r)}return l.createElement.apply(null,o)}h.displayName="MDXCreateElement"},1053:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>s,contentTitle:()=>r,default:()=>c,frontMatter:()=>a,metadata:()=>n,toc:()=>p});var l=o(7462),i=(o(7294),o(3905));const a={slug:"introducing-rollkit",title:"Introducing Rollkit: a modular rollup framework",authors:["AlCJoseph","alex-beckett"],tags:["Rollkit","Celestia"],description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation"},r=void 0,n={permalink:"/pr-preview/pr-192/blog/introducing-rollkit",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-02-21-introducing-rollkit.mdx",source:"@site/blog/2023-02-21-introducing-rollkit.mdx",title:"Introducing Rollkit: a modular rollup framework",description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation",date:"2023-02-21T00:00:00.000Z",formattedDate:"February 21, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"},{label:"Celestia",permalink:"/pr-preview/pr-192/blog/tags/celestia"}],readingTime:5.985,hasTruncateMarker:!1,authors:[{name:"Joseph Al-Chami",url:"https://github.com/AlCJoseph",imageURL:"https://github.com/AlCJoseph.png",key:"AlCJoseph"},{name:"Alex Beckett",url:"https://github.com/alex-beckett",imageURL:"https://github.com/alex-beckett.png",key:"alex-beckett"}],frontMatter:{slug:"introducing-rollkit",title:"Introducing Rollkit: a modular rollup framework",authors:["AlCJoseph","alex-beckett"],tags:["Rollkit","Celestia"],description:"Neutral and independent from Celestia, Rollkit serves as a community-led public good that empowers developers with the freedom to deploy throughout the modular stack and accelerate innovation"},prevItem:{title:"Sovereign rollups on Bitcoin with Rollkit",permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin"}},s={authorsImageUrls:[void 0,void 0]},p=[{value:"Tl;dr:",id:"tldr",level:2},{value:"Deploying a new chain is hard",id:"deploying-a-new-chain-is-hard",level:2},{value:"Freedom to deploy",id:"freedom-to-deploy",level:2},{value:"Vision for Rollkit",id:"vision-for-rollkit",level:2},{value:"Execution environments",id:"execution-environments",level:3},{value:"Sequencers",id:"sequencers",level:3},{value:"Proof schemes",id:"proof-schemes",level:3},{value:"Rollup types",id:"rollup-types",level:3},{value:"Rollkit is neutral",id:"rollkit-is-neutral",level:2},{value:"Next steps",id:"next-steps",level:2}],u={toc:p};function c(e){let{components:t,...a}=e;return(0,i.kt)("wrapper",(0,l.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"The original version of this blog post can be found on the ",(0,i.kt)("a",{parentName:"em",href:"https://blog.celestia.org/introducing-rollkit-a-modular-rollup-framework/"},"Celestia blog"),".")),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit blog cover",src:o(6197).Z,width:"3000",height:"1500"})),(0,i.kt)("p",null,"Today, we\u2019re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation."),(0,i.kt)("p",null,"Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/informalsystems/tendermint/tree/main/abci"},"ABCI"),"-compatible blockchain app, including Cosmos chains."),(0,i.kt)("p",null,"In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at ",(0,i.kt)("a",{parentName:"p",href:"/"},"rollkit.dev"),"."),(0,i.kt)("h2",{id:"tldr"},"Tl;dr:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"You can now ",(0,i.kt)("a",{parentName:"li",href:"/"},"build with Rollkit")," on Celestia\u2019s Mocha testnet. Check out the ",(0,i.kt)("a",{parentName:"li",href:"/"},"docs")),(0,i.kt)("li",{parentName:"ul"},"You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit\u2019s modular framework"),(0,i.kt)("li",{parentName:"ul"},"Join our Rollkit developer calls that begin in April to help guide its development")),(0,i.kt)("h2",{id:"deploying-a-new-chain-is-hard"},"Deploying a new chain is hard"),(0,i.kt)("p",null,"Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility."),(0,i.kt)("p",null,"For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs."),(0,i.kt)("p",null,"In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could."),(0,i.kt)("h2",{id:"freedom-to-deploy"},"Freedom to deploy"),(0,i.kt)("p",null,"Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain."),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit comparison table",src:o(3988).Z,width:"1600",height:"374"})),(0,i.kt)("p",null,"Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain."),(0,i.kt)("p",null,"With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don\u2019t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers."),(0,i.kt)("h2",{id:"vision-for-rollkit"},"Vision for Rollkit"),(0,i.kt)("p",null,"In the spirit of modularity, Rollkit\u2019s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit."),(0,i.kt)("p",null,"In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit\u2019s customizable stack will enable developers to bring their products to market faster and with more flexibility."),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"Rollkit lego image",src:o(6194).Z,width:"1600",height:"1322"})),(0,i.kt)("h3",{id:"execution-environments"},"Execution environments"),(0,i.kt)("p",null,"Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch."),(0,i.kt)("h3",{id:"sequencers"},"Sequencers"),(0,i.kt)("p",null,"Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers."),(0,i.kt)("h3",{id:"proof-schemes"},"Proof schemes"),(0,i.kt)("p",null,"Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs."),(0,i.kt)("h3",{id:"rollup-types"},"Rollup types"),(0,i.kt)("p",null,"Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups."),(0,i.kt)("p",null,"Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its ",(0,i.kt)("a",{parentName:"p",href:"/docs/rollkit-stack"},"current state"),", Rollkit rollups are ",(0,i.kt)("a",{parentName:"p",href:"https://blog.celestia.org/sovereign-rollup-chains"},"sovereign rollups")," with single sequencers, with support for a pessimistic mode and a ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/manav/state_fraud_proofs_adr/docs/lazy-adr/adr-009-state-fraud-proofs.md"},"work-in-progress optimistic mode"),". ",(0,i.kt)("a",{parentName:"p",href:"/docs/category/tutorials"},"Integration tutorials")," are ready and available with Cosmos SDK, Ethermint, and CosmWasm."),(0,i.kt)("p",null,"We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action. "),(0,i.kt)("h2",{id:"rollkit-is-neutral"},"Rollkit is neutral"),(0,i.kt)("p",null,"Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract."),(0,i.kt)("p",null,"Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/EclipseFND"},"Eclipse")," (Solana VM rollups), ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/dymensionXYZ"},"Dymension")," (settled Cosmos rollups), ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/sovereign_labs"},"Sovereign Labs")," (sovereign ZK rollups), and ",(0,i.kt)("a",{parentName:"p",href:"https://twitter.com/optimismFND"},"Optimism")," (EVM rollups)."),(0,i.kt)("p",null,"To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site."),(0,i.kt)("p",null,"This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/567b9f500db8055289365ea63450cefe4b135077/da/da.go#L60"},"data availability interface"),"."),(0,i.kt)("p",null,"The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it."),(0,i.kt)("p",null,"Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack."),(0,i.kt)("p",null,"We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it\u2019s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up."),(0,i.kt)("h2",{id:"next-steps"},"Next steps"),(0,i.kt)("p",null,"Moving towards a community-led project means increased visibility, transparency and inclusivity. That\u2019s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit. "),(0,i.kt)("p",null,"Learn more about how Rollkit works ",(0,i.kt)("a",{parentName:"p",href:"/"},"on the new Rollkit website")," (you're already on it!). And don\u2019t forget to check out the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit"},"Rollkit repo")," too."),(0,i.kt)("p",null,"Let\u2019s build modular together."))}c.isMDXComponent=!0},3988:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/comparison-table-7c865eb80a6add486978246e68eb69fa.png"},6197:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/rollkit-blog-cover-8cba9a7759f1f728fb99c4bb344ef12b.png"},6194:(e,t,o)=>{o.d(t,{Z:()=>l});const l=o.p+"assets/images/rollkit-lego-67992ef3767eb2c35eff95a0240749bd.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/85430e88.6b8aacab.js b/pr-preview/pr-192/assets/js/85430e88.6b8aacab.js deleted file mode 100644 index 5dbe95c27..000000000 --- a/pr-preview/pr-192/assets/js/85430e88.6b8aacab.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[9643],{3490:e=>{e.exports=JSON.parse('{"label":"Rollkit","permalink":"/pr-preview/pr-192/blog/tags/rollkit","allTagsPath":"/pr-preview/pr-192/blog/tags","count":3}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/8f6681fc.2d347811.js b/pr-preview/pr-192/assets/js/8f6681fc.2d347811.js deleted file mode 100644 index 55efbc94a..000000000 --- a/pr-preview/pr-192/assets/js/8f6681fc.2d347811.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5191],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>h});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var s=a.createContext({}),u=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=u(e.components);return a.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=u(n),m=i,h=p["".concat(s,".").concat(m)]||p[m]||d[m]||r;return n?a.createElement(h,o(o({ref:t},c),{},{components:n})):a.createElement(h,o({ref:t},c))}));function h(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,o=new Array(r);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:i,o[1]=l;for(var u=2;u<r;u++)o[u]=n[u];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},4254:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>r,metadata:()=>l,toc:()=>u});var a=n(7462),i=(n(7294),n(3905));const r={sidebar_label:"Ethermint (EVM) tutorial",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Celestia and Rollkit"},o="\u29eb Ethermint (EVM) rollup",l={unversionedId:"tutorials/ethermint",id:"tutorials/ethermint",title:"\u29eb Ethermint (EVM) rollup",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Celestia and Rollkit",source:"@site/docs/tutorials/ethermint.md",sourceDirName:"tutorials",slug:"/tutorials/ethermint",permalink:"/pr-preview/pr-192/docs/tutorials/ethermint",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/ethermint.md",tags:[],version:"current",frontMatter:{sidebar_label:"Ethermint (EVM) tutorial",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Celestia and Rollkit"},sidebar:"docs",previous:{title:"Advanced",permalink:"/pr-preview/pr-192/docs/category/advanced"}},s={},u=[{value:"\ud83d\udc8e Ethermint dependencies",id:"-ethermint-dependencies",level:2},{value:"\ud83d\udcbb Hardware requirements",id:"-hardware-requirements",level:3},{value:"\ud83d\udc7e Setting up your Ethermint node",id:"-setting-up-your-ethermint-node",level:3},{value:"\ud83c\udfc3 Golang dependency",id:"-golang-dependency",level:3},{value:"\ud83d\uddde\ufe0f Rollkit installation",id:"\ufe0f-rollkit-installation",level:2},{value:"\ud83d\udc79 ethermintd installation",id:"-ethermintd-installation",level:3},{value:"\ud83d\udcbb Setting up your environment for Ethermint on Celestia",id:"-setting-up-your-environment-for-ethermint-on-celestia",level:2},{value:"\ud83c\udfc3\u200d\u2642\ufe0f Run a Celestia light node",id:"\ufe0f-run-a-celestia-light-node",level:3},{value:"\ud83c\udf00 Instantiating the Ethermint rollup",id:"-instantiating-the-ethermint-rollup",level:3},{value:"\ud83d\udcc3 Deploy a Solidity smart contract on Ethermint sovereign rollup with Foundry",id:"-deploy-a-solidity-smart-contract-on-ethermint-sovereign-rollup-with-foundry",level:2},{value:"\u2692\ufe0f About Foundry",id:"\ufe0f-about-foundry",level:3},{value:"\ud83c\udfac Getting started",id:"-getting-started",level:3},{value:"\u26a1\ufe0f Initialize development environment",id:"\ufe0f-initialize-development-environment",level:4},{value:"\ud83d\udcc3 Updating the contract and tests",id:"-updating-the-contract-and-tests",level:4},{value:"\ud83d\udcd2 Updating the deployment script",id:"-updating-the-deployment-script",level:4},{value:"\ud83c\udfe0 Deploying locally",id:"-deploying-locally",level:4},{value:"\ud83d\udfe2 Deploying to the Ethermint sovereign rollup",id:"-deploying-to-the-ethermint-sovereign-rollup",level:4}],c={toc:u};function p(e){let{components:t,...n}=e;return(0,i.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"-ethermint-evm-rollup"},"\u29eb Ethermint (EVM) rollup"),(0,i.kt)("p",null,"Ethermint is a Comsos-SDK library that integrates an EVM compiler\nfrom Geth."),(0,i.kt)("p",null,"This would allow you to deploy Solidity or Vyper Ethereum smart contracts\nin order to build Ethereum-based applications."),(0,i.kt)("p",null,"In this tutorial, we will be going over how to use Rollkit to deploy\nan Ethereum-based sovereign rollup that uses Cosmos-SDK and Ethermint."),(0,i.kt)("p",null,"You can learn more about Ethermint ",(0,i.kt)("a",{parentName:"p",href:"https://docs.ethermint.zone"},"here"),"."),(0,i.kt)("admonition",{title:"note",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"This tutorial will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"Issue ticket"),"\nor let us know in our ",(0,i.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),".")),(0,i.kt)("admonition",{title:"caution",type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"The script for this tutorial is built for Celestia's\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspacerace testnet"),".\nIf you choose to use Mocha testnet or Arabica devnet,\nyou will need to modify the script manually.")),(0,i.kt)("p",null,"In this tutorial, we will go over the following:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#ethermint-dependencies"},"Setting Up Your Ethermint Dependencies")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#rollkit-installation"},"Setting Up Rollkit on Ethermint")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#setting-up-your-environment-for-ethermint-on-celestia"},"Instantiate a local network for your Ethermint chain connected to Celestia")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"#deploy-a-solidity-smart-contract-on-ethermint-sovereign-rollup-with-foundry"},"Deploying an Ethereum smart contract on your Ethermint Rollup with Foundry"))),(0,i.kt)("h2",{id:"-ethermint-dependencies"},"\ud83d\udc8e Ethermint dependencies"),(0,i.kt)("p",null,"This section will guide you through installing the dependencies\nyou need for the deployment process of an Ethermint Sovereign Rollup\non Celestia."),(0,i.kt)("h3",{id:"-hardware-requirements"},"\ud83d\udcbb Hardware requirements"),(0,i.kt)("p",null,"The following hardware minimum requirements are recommended for running\nthe full storage node:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Memory: 8 GB RAM"),(0,i.kt)("li",{parentName:"ul"},"CPU: Quad-Core"),(0,i.kt)("li",{parentName:"ul"},"Disk: 250 GB SSD Storage"),(0,i.kt)("li",{parentName:"ul"},"Bandwidth: 1 Gbps for Download/100 Mbps for Upload")),(0,i.kt)("h3",{id:"-setting-up-your-ethermint-node"},"\ud83d\udc7e Setting up your Ethermint node"),(0,i.kt)("p",null,"The following tutorial is done on an Ubuntu Linux 20.04 (LTS) x64 instance machine."),(0,i.kt)("h3",{id:"-golang-dependency"},"\ud83c\udfc3 Golang dependency"),(0,i.kt)("p",null,"The Golang version used for this tutorial is v1.18+"),(0,i.kt)("p",null,"If you are using a Linux distribution, you can install Golang\nby following our tutorial ",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment#install-golang"},"here"),"."),(0,i.kt)("h2",{id:"\ufe0f-rollkit-installation"},"\ud83d\uddde\ufe0f Rollkit installation"),(0,i.kt)("h3",{id:"-ethermintd-installation"},"\ud83d\udc79 ethermintd installation"),(0,i.kt)("p",null,"Here, we are going to pull down the ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermint")," from the\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/ethermint"},"Celestia repository"),".\nWe will install Rollkit to this version of Ethermint.\nRollkit is a drop-in replacement for Tendermint that allows\nCosmos-SDK applications to connect to Celestia's data availability network."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"git clone https://github.com/celestiaorg/ethermint.git\ncd ethermint\nmake install\n")),(0,i.kt)("p",null,"You can check if ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermintd")," is installed by running the following\ncommand:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"ethermintd\n")),(0,i.kt)("h2",{id:"-setting-up-your-environment-for-ethermint-on-celestia"},"\ud83d\udcbb Setting up your environment for Ethermint on Celestia"),(0,i.kt)("p",null,"Now the ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermintd")," binary is built, we need to setup a local network\nthat communicates between ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermintd")," and Rollkit."),(0,i.kt)("h3",{id:"\ufe0f-run-a-celestia-light-node"},"\ud83c\udfc3\u200d\u2642\ufe0f Run a Celestia light node"),(0,i.kt)("p",null,"All sovereign rollups need to submit their transaction data to\nCelestia."),(0,i.kt)("p",null,"Here, we must first setup a Celestia Light Node with testnet tokens."),(0,i.kt)("p",null,"You can do this by following this tutorial ",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/developers/node-tutorial"},"here"),"."),(0,i.kt)("h3",{id:"-instantiating-the-ethermint-rollup"},"\ud83c\udf00 Instantiating the Ethermint rollup"),(0,i.kt)("p",null,"With a Celestia Light Node running in one terminal session,\nwe can proceed to generate the Ethermint rollup."),(0,i.kt)("p",null,"In the ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermint")," directory, we have a helpful bash script that\nallows you to instantiate a local Ethermint sovereign rollup on Celestia."),(0,i.kt)("p",null,"Run the following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"bash init.sh\n")),(0,i.kt)("p",null,"This bash script does everything needed to initialize your Ethermint\nrollup."),(0,i.kt)("p",null,"First, we need to setup some environment variables."),(0,i.kt)("admonition",{title:"Networks",type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"The commands below are for Blockspace Race. If you're using Mocha or Arabica, you'll need to\nreplace the RPC endpoint with ",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/arabica-devnet#rpc-endpoints"},"one for Arabica")," or ",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/mocha-testnet#rpc-endpoints"},"one for Mocha"),".")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"NAMESPACE_ID=$(openssl rand -hex 8)\nDA_BLOCK_HEIGHT=$(curl https://rpc-blockspacerace.pops.one/block | jq -r '.result.block.header.height')\n")),(0,i.kt)("p",null,"If you are running this on Celestia's\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/mocha-testnet"},"Mocha testnet"),"\nor Arabica devnet, you need to run your light node with an account\nthat has Mocha or Arabica tokens. Visit the faucet\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/arabica-devnet#arabica-devnet-faucet"},"here"),"."),(0,i.kt)("p",null,"With this setup complete, we can now start our Ethermint Rollup:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config=\'{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6000}\' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height $DA_BLOCK_HEIGHT \n')),(0,i.kt)("p",null,"You should start seeing logs about the chain starting.\nThey will look similar to below:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'1:27AM INF Unlocking keyring\n1:27AM INF starting ABCI with Tendermint\n1:27AM INF service start impl=EventBus module=events msg={}\n1:27AM INF service start impl=PubSub module=pubsub msg={}\nbadger 2022/11/23 01:27:54 INFO: All 0 tables opened in 0s\nbadger 2022/11/23 01:27:54 INFO: Discard stats nextEmptySlot: 0\nbadger 2022/11/23 01:27:54 INFO: Set nextTxnTs to 0\n1:27AM INF service start impl=IndexerService module=txindex msg={}\n1:27AM INF WARNING: using default DA block time DABlockTime=30000 module=BlockManager\n1:27AM INF initializing blockchain state from genesis.json\n1:27AM INF created new capability module=ibc name=ports/transfer\n1:27AM INF port binded module=x/ibc/port port=transfer\n1:27AM INF claimed capability capability=1 module=transfer name=ports/transfer\n1:27AM INF asserting crisis invariants inv=1/11 module=x/crisis name=gov/module-account\n1:27AM INF asserting crisis invariants inv=2/11 module=x/crisis name=staking/module-accounts\n1:27AM INF asserting crisis invariants inv=3/11 module=x/crisis name=staking/nonnegative-power\n1:27AM INF asserting crisis invariants inv=4/11 module=x/crisis name=staking/positive-delegation\n1:27AM INF asserting crisis invariants inv=5/11 module=x/crisis name=staking/delegator-shares\n1:27AM INF asserting crisis invariants inv=6/11 module=x/crisis name=bank/nonnegative-outstanding\n1:27AM INF asserting crisis invariants inv=7/11 module=x/crisis name=bank/total-supply\n1:27AM INF asserting crisis invariants inv=8/11 module=x/crisis name=distribution/nonnegative-outstanding\n1:27AM INF asserting crisis invariants inv=9/11 module=x/crisis name=distribution/can-withdraw\n1:27AM INF asserting crisis invariants inv=10/11 module=x/crisis name=distribution/reference-count\n1:27AM INF asserting crisis invariants inv=11/11 module=x/crisis name=distribution/module-account\n1:27AM INF asserted all invariants duration=3.783918 height=0 module=x/crisis\n1:27AM INF service start impl=RPC msg={}\n1:27AM INF service start impl=Node msg={}\n1:27AM INF serving HTTP listen address={"IP":"127.0.0.1","Port":26657,"Zone":""}\n1:27AM INF starting P2P client\n1:27AM INF listening on address=/ip4/143.244.145.92/tcp/26656/p2p/12D3KooWCrCqYheUBURCzzUqgxWFVFvFYPJ6nonTPN9uVQ4cXK5H module=p2p\n1:27AM INF listening on address=/ip4/127.0.0.1/tcp/26656/p2p/12D3KooWCrCqYheUBURCzzUqgxWFVFvFYPJ6nonTPN9uVQ4cXK5H module=p2p\n1:27AM INF no seed nodes - only listening for connections module=p2p\n1:27AM INF starting Celestia Data Availability Layer Client baseURL=http://localhost:26659 module=da_client\n1:27AM INF working in aggregator mode block time=30000\n1:27AM INF Creating and publishing block height=1 module=BlockManager\n1:27AM INF minted coins from module account amount=2059726034250856481aphoton from=mint module=x/bank\n1:27AM INF submitting block to DA layer height=1 module=BlockManager\n1:28AM INF Starting JSON-RPC server address=0.0.0.0:8545\n1:28AM INF Starting JSON WebSocket server address=0.0.0.0:8546\n1:28AM INF successfully submitted rollkit block to DA layer daHeight=25422 module=BlockManager rollkitHeight=1\n1:28AM INF commit synced commit=436F6D6D697449447B5B323130203138352031373920362035322031333820373020313032203135322038302032323920313232203132342036332031382032313920313039203337203832203631203334203139302031323520393020323133203835203232382032323420323232203134203739203131305D3A317D\n1:28AM INF indexed block height=1 module=txindex\n1:28AM INF Creating and publishing block height=2 module=BlockManager\n1:28AM INF minted coins from module account amount=2059726403014551280aphoton from=mint module=x/bank\n1:28AM INF submitting block to DA layer height=2 module=BlockManager\n1:28AM INF successfully submitted rollkit block to DA layer daHeight=25423 module=BlockManager rollkitHeight=2\n1:28AM INF commit synced commit=436F6D6D697449447B5B3630203231332038372032313820383920313920323034203230322031363320383120323235203235352036352032323820313530203232392032333320323139203233322032343420313334203337203134342031303320313634203138382031393720323339203230342032303120323138203130325D3A327D\n1:28AM INF indexed block height=2 module=txindex\n1:28AM INF Creating and publishing block height=3 module=BlockManager\n1:28AM INF minted coins from module account amount=2059726771778267119aphoton from=mint module=x/bank\n1:28AM INF submitting block to DA layer height=3 module=BlockManager\n1:29AM INF successfully submitted rollkit block to DA layer daHeight=25424 module=BlockManager rollkitHeight=3\n1:29AM INF commit synced commit=436F6D6D697449447B5B313520323038203831203131203235332032322037322031393020333220323130203634203235332032303920313839203934203137203431203135203230302039362031383920323820313736203132332037352032392031393320313831203134312032303520323231203232325D3A337D\n1:29AM INF indexed block height=3 module=txindex\n1:29AM INF Creating and publishing block height=4 module=BlockManager\n1:29AM INF minted coins from module account amount=2059727140542003996aphoton from=mint module=x/bank\n1:29AM INF submitting block to DA layer height=4 module=BlockManager\n1:29AM INF successfully submitted rollkit block to DA layer daHeight=25425 module=BlockManager rollkitHeight=4\n1:29AM INF commit synced commit=436F6D6D697449447B5B313433203332203639203732203134342034352037302034302032392032303120393720313137203235312031393320313738203137362031353920323038203231372036312032362031353720353320393820323234203230352031373020313920313034203138372031323220385D3A347D\n1:29AM INF indexed block height=4 module=txindex\n1:29AM INF Creating and publishing block height=5 module=BlockManager\n')),(0,i.kt)("p",null,"With that, we have kickstarted our ",(0,i.kt)("inlineCode",{parentName:"p"},"ethermintd")," network!"),(0,i.kt)("h2",{id:"-deploy-a-solidity-smart-contract-on-ethermint-sovereign-rollup-with-foundry"},"\ud83d\udcc3 Deploy a Solidity smart contract on Ethermint sovereign rollup with Foundry"),(0,i.kt)("p",null,"In this guide you'll learn how to deploy a Solidity smart contract to\nthe Ethermint chain you just instantiated on Celestia with\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/foundry-rs/foundry"},"Foundry"),"."),(0,i.kt)("h3",{id:"\ufe0f-about-foundry"},"\u2692\ufe0f About Foundry"),(0,i.kt)("p",null,"Foundry is a portable, fast and modular toolkit for Ethereum application development."),(0,i.kt)("p",null,"Foundry is made up of three components:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/foundry-rs/foundry/tree/master/forge"},(0,i.kt)("strong",{parentName:"a"},"Forge"))," - Ethereum\ntesting framework (like Truffle, Hardhat and DappTools)."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/foundry-rs/foundry/tree/master/cast"},(0,i.kt)("strong",{parentName:"a"},"Cast"))," - CLI for\ninteracting with EVM smart contracts, sending transactions, and getting chain data."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/foundry-rs/foundry/tree/master/anvil"},(0,i.kt)("strong",{parentName:"a"},"Anvil"))," - Local\nEthereum node, similar to Ganache or Hardhat Network.")),(0,i.kt)("p",null,"We'll use all three to create, test, and deploy our Solidity project."),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"To learn more about Foundry, check out the ",(0,i.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh"},"Foundry Book"),".")),(0,i.kt)("h3",{id:"-getting-started"},"\ud83c\udfac Getting started"),(0,i.kt)("h4",{id:"\ufe0f-initialize-development-environment"},"\u26a1\ufe0f Initialize development environment"),(0,i.kt)("p",null,"First, be sure to\n",(0,i.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/getting-started/installation.html"},"install Foundry"),"\non your local development environment."),(0,i.kt)("p",null,"Next, create a new project and change into the directory:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"forge init celestia-ethermint-app\ncd celestia-ethermint-app\n")),(0,i.kt)("p",null,"Foundry has created an example smart contract located at ",(0,i.kt)("inlineCode",{parentName:"p"},"src/Counter.sol"),"."),(0,i.kt)("h4",{id:"-updating-the-contract-and-tests"},"\ud83d\udcc3 Updating the contract and tests"),(0,i.kt)("p",null,"Let's update the contracts to include a basic counter example. Open the\n",(0,i.kt)("inlineCode",{parentName:"p"},"Counter.sol")," file in the ",(0,i.kt)("inlineCode",{parentName:"p"},"src")," directory and add the following code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ncontract Counter {\n int private count;\n \n constructor(int _count) {\n count = _count;\n }\n\n function incrementCounter() public {\n count += 1;\n }\n function decrementCounter() public {\n count -= 1;\n }\n\n function getCount() public view returns (int) {\n return count;\n }\n}\n")),(0,i.kt)("p",null,"Next, let's create a test for this contract."),(0,i.kt)("p",null,"Open ",(0,i.kt)("inlineCode",{parentName:"p"},"test/Counter.T.Sol")," and update the code with the following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport \"forge-std/Test.sol\";\nimport 'src/Counter.sol';\n\ncontract CounterTest is Test {\n Counter counter;\n function setUp() public {\n counter = new Counter(10);\n }\n\n function testGetCount() public {\n int value = counter.getCount();\n assertEq(value, 10);\n emit log_int(value);\n }\n\n function testIncrement() public {\n counter.incrementCounter();\n counter.incrementCounter();\n int value = counter.getCount();\n assertEq(value, 12);\n emit log_int(value);\n }\n\n function testDecrement() public {\n counter.decrementCounter();\n int value = counter.getCount();\n assertEq(value, 9);\n emit log_int(value);\n }\n}\n")),(0,i.kt)("p",null,"Foundry uses ",(0,i.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/reference/ds-test.html"},"Dappsys Test")," to\nprovide basic logging and assertion functionality. It's included in the Forge\nStandard Library."),(0,i.kt)("p",null,"Here, we are using ",(0,i.kt)("inlineCode",{parentName:"p"},"assertEq")," to assert equality. You can view all of the assertion\nfunctions available\n",(0,i.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/reference/ds-test.html?highlight=log_int#asserting"},"here"),"."),(0,i.kt)("p",null,"Next, we can test the contract using ",(0,i.kt)("strong",{parentName:"p"},"Forge")," with the following command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"forge test -vv\n")),(0,i.kt)("p",null,"A successful test will have output similar to the following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"[\u280a] Compiling...\n[\u2830] Installing solc version 0.8.17\n[\u2812] Successfully installed solc 0.8.17\n[\u2806] Compiling 18 files with 0.8.17\n[\u2811] Solc 0.8.17 finished in 3.59s\nCompiler run successful\n\nRunning 3 tests for test/Counter.t.sol:ContractTest\n[PASS] testDecrement() (gas: 12350)\nLogs:\n 9\n\n[PASS] testGetCount() (gas: 8510)\nLogs:\n 10\n\n[PASS] testIncrement() (gas: 13285)\nLogs:\n 12\n\nTest result: ok. 3 passed; 0 failed; finished in 2.24ms\n")),(0,i.kt)("h4",{id:"-updating-the-deployment-script"},"\ud83d\udcd2 Updating the deployment script"),(0,i.kt)("p",null,"Now that we've tested the contract, let's try deploying it locally using\n",(0,i.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/tutorials/solidity-scripting.html"},"Solidity Scripting"),"."),(0,i.kt)("p",null,"To do so, update the deloyment script at ",(0,i.kt)("inlineCode",{parentName:"p"},"script/Counter.s.sol")," with the\nfollowing code:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-solidity"},'// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport "forge-std/Script.sol";\n\nimport {Counter} from "src/Counter.sol";\n\ncontract CounterScript is Script {\n function setUp() public {}\n\n function run() public {\n vm.startBroadcast();\n new Counter(10);\n vm.stopBroadcast();\n }\n}\n')),(0,i.kt)("p",null,"Now we can use this script to deploy our smart contract to either a live or\ntest network."),(0,i.kt)("h4",{id:"-deploying-locally"},"\ud83c\udfe0 Deploying locally"),(0,i.kt)("p",null,"Next start Anvil, the local testnet:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"anvil --port 9545\n")),(0,i.kt)("p",null,"Once started, Anvil will give you a local RPC endpoint as well as a handful\nof Private Keys and Accounts that you can use."),(0,i.kt)("p",null,"Set ",(0,i.kt)("inlineCode",{parentName:"p"},"ANVIL_KEY")," with one of the private keys generated by running:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"export ANVIL_KEY=<anvil-private-key>\n")),(0,i.kt)("p",null,"And set the RPC URL as an environment variable:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"export RPC_URL=http://127.0.0.1:9545\n")),(0,i.kt)("p",null,"We can now use the local RPC along with one of the private keys to\ndeploy locally from the ",(0,i.kt)("inlineCode",{parentName:"p"},"celestia-ethermint-app")," directory:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"forge script script/Counter.s.sol:CounterScript --fork-url \\\n$RPC_URL --private-key $ANVIL_KEY --broadcast\n")),(0,i.kt)("p",null,"Once the contract has been deployed locally, Anvil will log out the contract address."),(0,i.kt)("p",null,"Next, set the contract address as an environment variable:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"export CONTRACT_ADDRESS=<contract-address>\n")),(0,i.kt)("p",null,"We can then test sending transactions to it with ",(0,i.kt)("inlineCode",{parentName:"p"},"cast send"),"."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'cast send $CONTRACT_ADDRESS "incrementCounter()" \\\n--private-key $ANVIL_KEY --rpc-url $RPC_URL\n')),(0,i.kt)("p",null,"We can then perform read operations with ",(0,i.kt)("inlineCode",{parentName:"p"},"cast call"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url $RPC_URL\n')),(0,i.kt)("h4",{id:"-deploying-to-the-ethermint-sovereign-rollup"},"\ud83d\udfe2 Deploying to the Ethermint sovereign rollup"),(0,i.kt)("p",null,"Now that we've deployed and tested locally, we can deploy to our\nEthermint chain."),(0,i.kt)("p",null,"First, we will need to export the private key generated by\nthe ethermint ",(0,i.kt)("inlineCode",{parentName:"p"},"init.sh")," script:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"PRIVATE_KEY=$(ethermintd keys unsafe-export-eth-key mykey --keyring-backend test)\n")),(0,i.kt)("blockquote",null,(0,i.kt)("p",{parentName:"blockquote"},"NOTE: Here, the key name from ",(0,i.kt)("inlineCode",{parentName:"p"},"init.sh")," is ",(0,i.kt)("inlineCode",{parentName:"p"},"mykey")," but you can modify\nthe ",(0,i.kt)("inlineCode",{parentName:"p"},"init.sh")," to change the name of your key.")),(0,i.kt)("p",null,"Now, we can start deploying the smart contract to our Ethermint chain."),(0,i.kt)("p",null,"To do so, run the following script from the\n",(0,i.kt)("inlineCode",{parentName:"p"},"celestia-ethermint-app")," directory:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"forge script script/Counter.s.sol:CounterScript \\\n--rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast\n")),(0,i.kt)("p",null,"Set the contract address in the output as the ",(0,i.kt)("inlineCode",{parentName:"p"},"CONTRACT_ADDRESS")," variable:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"export CONTRACT_ADDRESS=<new-contract-address>\n")),(0,i.kt)("p",null,"Once the contract has been deployed to the Ethermint rollup, we can\nuse ",(0,i.kt)("inlineCode",{parentName:"p"},"cast send")," to test sending transactions to it:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'cast send $CONTRACT_ADDRESS "incrementCounter()" \\\n--rpc-url http://localhost:8545 --private-key $PRIVATE_KEY \n')),(0,i.kt)("p",null,"We can then perform read operations with ",(0,i.kt)("inlineCode",{parentName:"p"},"cast call"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url http://localhost:8545\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/9064f397.563e2664.js b/pr-preview/pr-192/assets/js/9064f397.563e2664.js deleted file mode 100644 index 4f6665a53..000000000 --- a/pr-preview/pr-192/assets/js/9064f397.563e2664.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5326],{8612:e=>{e.exports=JSON.parse('{"label":"Celestia","permalink":"/pr-preview/pr-192/blog/tags/celestia","allTagsPath":"/pr-preview/pr-192/blog/tags","count":1}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/935f2afb.9deca9a6.js b/pr-preview/pr-192/assets/js/935f2afb.9deca9a6.js deleted file mode 100644 index 33c771516..000000000 --- a/pr-preview/pr-192/assets/js/935f2afb.9deca9a6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[53],{1109:l=>{l.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"docs":[{"type":"link","label":"Introduction","href":"/pr-preview/pr-192/docs/intro","docId":"intro"},{"type":"link","label":"Rollkit stack","href":"/pr-preview/pr-192/docs/rollkit-stack","docId":"rollkit-stack"},{"type":"link","label":"Transaction flow","href":"/pr-preview/pr-192/docs/transaction-flow","docId":"transaction-flow"},{"type":"category","label":"Tutorials","collapsed":false,"items":[{"type":"category","label":"Beginner","collapsed":false,"items":[{"type":"link","label":"Building & deploying a rollup","href":"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup","docId":"tutorials/building-and-deploying-a-rollup"},{"type":"link","label":"GM world tutorial","href":"/pr-preview/pr-192/docs/tutorials/gm-world","docId":"tutorials/gm-world"},{"type":"link","label":"GM world frontend tutorial","href":"/pr-preview/pr-192/docs/tutorials/gm-world-frontend","docId":"tutorials/gm-world-frontend"},{"type":"link","label":"Recipe book tutorial","href":"/pr-preview/pr-192/docs/tutorials/recipe-book","docId":"tutorials/recipe-book"},{"type":"link","label":"How to restart your rollup","href":"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup","docId":"tutorials/restart-rollkit-rollup"}],"collapsible":true,"href":"/pr-preview/pr-192/docs/category/beginner"},{"type":"category","label":"Intermediate","collapsed":false,"items":[{"type":"link","label":"Wordle tutorial","href":"/pr-preview/pr-192/docs/tutorials/wordle","docId":"tutorials/wordle"},{"type":"link","label":"CosmWasm tutorial","href":"/pr-preview/pr-192/docs/tutorials/cosmwasm","docId":"tutorials/cosmwasm"}],"collapsible":true,"href":"/pr-preview/pr-192/docs/category/intermediate"},{"type":"category","label":"Advanced","collapsed":false,"items":[{"type":"link","label":"Ethermint (EVM) tutorial","href":"/pr-preview/pr-192/docs/tutorials/ethermint","docId":"tutorials/ethermint"},{"type":"link","label":"Full-stack modular dapp with Celestia","href":"https://docs.celestia.org/developers/full-stack-modular-development-guide"},{"type":"link","label":"Hyperlane + Celestia tutorial","href":"https://docs.hyperlane.xyz/docs/deploy/celestia-+-hyperlane"}],"collapsible":true,"href":"/pr-preview/pr-192/docs/category/advanced"}],"collapsible":true,"href":"/pr-preview/pr-192/docs/category/tutorials"}]},"docs":{"intro":{"id":"intro","title":"Introduction to Rollkit","description":"Intro to Rollkit, a modular framework for rollups.","sidebar":"docs"},"rollkit-stack":{"id":"rollkit-stack","title":"The Rollkit stack","description":"Intro to Rollkit\'s stack, a modular framework for rollups.","sidebar":"docs"},"transaction-flow":{"id":"transaction-flow","title":"Transaction flow","description":"Description of the flow of the Rollkit transaction.","sidebar":"docs"},"tutorials/bitcoin":{"id":"tutorials/bitcoin","title":"\u20bf Bitcoin rollup tutorial","description":"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Bitcoin and Rollkit"},"tutorials/building-and-deploying-a-rollup":{"id":"tutorials/building-and-deploying-a-rollup","title":"\ud83d\uddde\ufe0f Building a rollup and testnet deployment","description":"Build sovereign Cosmos-SDK and EVM applications","sidebar":"docs"},"tutorials/cosmwasm":{"id":"tutorials/cosmwasm","title":"\ud83d\uddde\ufe0f CosmWasm rollup","description":"Build a sovereign rollup with CosmWasm, Celestia, and Rollkit","sidebar":"docs"},"tutorials/ethermint":{"id":"tutorials/ethermint","title":"\u29eb Ethermint (EVM) rollup","description":"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Celestia and Rollkit","sidebar":"docs"},"tutorials/gm-world":{"id":"tutorials/gm-world","title":"GM world rollup","description":"Build a sovereign rollup with Ignite CLI, Celestia and Rollkit locally and on a testnet","sidebar":"docs"},"tutorials/gm-world-frontend":{"id":"tutorials/gm-world-frontend","title":"GM world frontend tutorial","description":"Build a frontend for your Rollkit rollup locally.","sidebar":"docs"},"tutorials/recipe-book":{"id":"tutorials/recipe-book","title":"\ud83e\udd57 Recipe book rollup","description":"Build a recipe book rollup with Ignite CLI, Celestia, and Rollkit","sidebar":"docs"},"tutorials/restart-rollkit-rollup":{"id":"tutorials/restart-rollkit-rollup","title":"\ud83d\udd04 How to restart your rollup","description":"Restart your Rollkit rollup safely","sidebar":"docs"},"tutorials/wordle":{"id":"tutorials/wordle","title":"\ud83d\udd79\ufe0f Wordle app","description":"Get started with Ignite CLI, Celestia and Rollkit","sidebar":"docs"}}}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/9434eb16.e6ae1522.js b/pr-preview/pr-192/assets/js/9434eb16.e6ae1522.js deleted file mode 100644 index c768b232f..000000000 --- a/pr-preview/pr-192/assets/js/9434eb16.e6ae1522.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8362],{4886:e=>{e.exports=JSON.parse('{"label":"Bitcoin","permalink":"/pr-preview/pr-192/blog/tags/bitcoin","allTagsPath":"/pr-preview/pr-192/blog/tags","count":1}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/94d5b9f3.6236b83d.js b/pr-preview/pr-192/assets/js/94d5b9f3.6236b83d.js deleted file mode 100644 index 559b9cf1f..000000000 --- a/pr-preview/pr-192/assets/js/94d5b9f3.6236b83d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3265],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>g});var a=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){l(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,l=function(e,t){if(null==e)return{};var n,a,l={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=a.createContext({}),c=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=c(n),h=l,g=u["".concat(s,".").concat(h)]||u[h]||d[h]||r;return n?a.createElement(g,o(o({ref:t},p),{},{components:n})):a.createElement(g,o({ref:t},p))}));function g(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=h;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[u]="string"==typeof e?e:l,o[1]=i;for(var c=2;c<r;c++)o[c]=n[c];return a.createElement.apply(null,o)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},740:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var a=n(7462),l=(n(7294),n(3905));const r={sidebar_label:"Bitcoin rollup tutorial",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Bitcoin and Rollkit"},o="\u20bf Bitcoin rollup tutorial",i={unversionedId:"tutorials/bitcoin",id:"tutorials/bitcoin",title:"\u20bf Bitcoin rollup tutorial",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Bitcoin and Rollkit",source:"@site/docs/tutorials/bitcoin.md",sourceDirName:"tutorials",slug:"/tutorials/bitcoin",permalink:"/pr-preview/pr-192/docs/tutorials/bitcoin",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/bitcoin.md",tags:[],version:"current",frontMatter:{sidebar_label:"Bitcoin rollup tutorial",description:"Build a sovereign rollup with Ethermint (EVM + Cosmos SDK), Bitcoin and Rollkit"}},s={},c=[{value:"\u2600\ufe0fIntroduction",id:"\ufe0fintroduction",level:2},{value:"\ud83d\udcd6 The stack",id:"-the-stack",level:3},{value:"\ud83d\udcbb Prerequisites",id:"-prerequisites",level:2},{value:"\ud83d\udee0\ufe0f Dependency setup",id:"\ufe0f-dependency-setup",level:2},{value:"\ud83c\udfc3 Golang",id:"-golang",level:3},{value:"\u2692\ufe0f Foundry",id:"\ufe0f-foundry",level:3},{value:"\ud83e\ude99 Install Bitcoin",id:"-install-bitcoin",level:3},{value:"\ud83d\udfe2 Running a local Bitcoin network",id:"-running-a-local-bitcoin-network",level:2},{value:"\ud83d\udc5b Create a wallet for the chain",id:"-create-a-wallet-for-the-chain",level:3},{value:"\ud83c\udfac Start generating blocks",id:"-start-generating-blocks",level:3},{value:"\ud83e\uddca Block height",id:"-block-height",level:4},{value:"\ud83e\uddca Block hash",id:"-block-hash",level:4},{value:"\ud83e\uddca Block header",id:"-block-header",level:4},{value:"\ud83c\udfac Restarting the local network",id:"-restarting-the-local-network",level:4},{value:"\ud83c\udfc3\u200d\u2640\ufe0f Running the Ethermint rollup",id:"\ufe0f-running-the-ethermint-rollup",level:2},{value:"\u26a1\ufe0f Initialize development environment",id:"\ufe0f-initialize-development-environment",level:3},{value:"\ud83d\udcd2 Updating the contract and tests",id:"-updating-the-contract-and-tests",level:3},{value:"\ud83d\udcdc Updating the deployment script",id:"-updating-the-deployment-script",level:3},{value:"\ud83c\udfe0 Deploying locally",id:"-deploying-locally",level:3},{value:"\ud83e\uddea Deploying to the Ethermint sovereign rollup",id:"-deploying-to-the-ethermint-sovereign-rollup",level:3}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,l.kt)("wrapper",(0,a.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h1",{id:"-bitcoin-rollup-tutorial"},"\u20bf Bitcoin rollup tutorial"),(0,l.kt)("h2",{id:"\ufe0fintroduction"},"\u2600\ufe0fIntroduction"),(0,l.kt)("p",null,"In this tutorial, we will explore how to use Rollkit to create sovereign rollups on Bitcoin. First, we will install Bitcoin Core to run a local testnet. Then, we will install and set up a Rollkit node to work with Bitcoin as a data availability layer. Lastly, we'll look at how to create a custom EVM execution environment and how to deploy a sovereign rollup on Bitcoin using Rollkit."),(0,l.kt)("p",null,"By the end of this tutorial, you will have a good understanding of how Rollkit works and how to create sovereign rollups on Bitcoin using Rollkit. You will also have the knowledge and skills needed to customize Rollkit with different execution environments and data availability layers, opening up new possibilities for creating scalable and efficient blockchain applications."),(0,l.kt)("p",null,"Read more in our ",(0,l.kt)("a",{parentName:"p",href:"../../../blog/sovereign-rollups-on-bitcoin"},"blog post"),"."),(0,l.kt)("p",null,(0,l.kt)("img",{alt:"rollkit-bitcoin",src:n(2626).Z,width:"3000",height:"2708"})),(0,l.kt)("h3",{id:"-the-stack"},"\ud83d\udcd6 The stack"),(0,l.kt)("p",null,"Sovereign rollups on Bitcoin are made possible through a module that allows Rollkit rollups to use Bitcoin for data availability. This integration opens up possibilities for developers to create rollups with arbitrary execution environments that inherit Bitcoin\u2019s data availability guarantees and security guarantees."),(0,l.kt)("p",null,"The Taproot upgrade and ",(0,l.kt)("a",{parentName:"p",href:"https://ordinals.com/"},"Ordinals")," usage of Bitcoin for publishing arbitrary data made it possible to integrate Bitcoin as a data availability layer into Rollkit. The modular design of Rollkit allows for easy integration of new data availability layers, making it possible to deploy sovereign rollups on Bitcoin."),(0,l.kt)("p",null,"The goal of Rollkit is to make it easy to build and customize rollups, enabling developers to build sovereign rollups on Bitcoin or customize Rollkit with different execution environments and data availability layers."),(0,l.kt)("h2",{id:"-prerequisites"},"\ud83d\udcbb Prerequisites"),(0,l.kt)("p",null,"An Ubuntu machine with:"),(0,l.kt)("ul",null,(0,l.kt)("li",{parentName:"ul"},"8GB RAM"),(0,l.kt)("li",{parentName:"ul"},"160 GB SSD"),(0,l.kt)("li",{parentName:"ul"},"Ubuntu 22.10"),(0,l.kt)("li",{parentName:"ul"},"4 core AMD CPU")),(0,l.kt)("h2",{id:"\ufe0f-dependency-setup"},"\ud83d\udee0\ufe0f Dependency setup"),(0,l.kt)("p",null,"First, make sure to update and upgrade the OS:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt update && sudo apt upgrade -y\n")),(0,l.kt)("p",null,"These are essential packages that are necessary to execute many tasks like downloading files, compiling, and monitoring the nodes:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install curl tar wget clang pkg-config libssl-dev jq build-essential git make ncdu snapd npm -y\n")),(0,l.kt)("p",null,"Now, we will install the remaining dependencies."),(0,l.kt)("h3",{id:"-golang"},"\ud83c\udfc3 Golang"),(0,l.kt)("p",null,"We will use golang to build and run our test networks. Install it for AMD with these commands:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'ver="1.19.1"\ncd $HOME\nwget "https://golang.org/dl/go$ver.linux-amd64.tar.gz"\nsudo rm -rf /usr/local/go\nsudo tar -C /usr/local -xzf "go$ver.linux-amd64.tar.gz"\nrm "go$ver.linux-amd64.tar.gz"\necho "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile\nsource $HOME/.bash_profile\ngo version\n')),(0,l.kt)("h3",{id:"\ufe0f-foundry"},"\u2692\ufe0f Foundry"),(0,l.kt)("p",null,"Install Foundry:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"curl -L https://foundry.paradigm.xyz/ | bash\n")),(0,l.kt)("p",null,"Set the path:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"source /root/.bashrc\n")),(0,l.kt)("p",null,"Run this to finish the installation of Foundry:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"foundryup\n")),(0,l.kt)("h3",{id:"-install-bitcoin"},"\ud83e\ude99 Install Bitcoin"),(0,l.kt)("p",null,"Running the rollup requires a local regtest Bitcoin node. You can set this up by running the following commands."),(0,l.kt)("p",null,"Install Bitcoin Core:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"sudo snap install bitcoin-core\n")),(0,l.kt)("p",null,"Check version:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli --version\n")),(0,l.kt)("h2",{id:"-running-a-local-bitcoin-network"},"\ud83d\udfe2 Running a local Bitcoin network"),(0,l.kt)("p",null,"Set up the config for regtest (local network):"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'bitcoin-core.daemon "-chain=regtest" "-rpcport=18332" "-rpcuser=rpcuser" "-rpcpassword=rpcpass" "-fallbackfee=0.000001" "-txindex=1"\n')),(0,l.kt)("h3",{id:"-create-a-wallet-for-the-chain"},"\ud83d\udc5b Create a wallet for the chain"),(0,l.kt)("p",null,"Open up a new terminal and run the following to create a wallet:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass createwallet w1\n")),(0,l.kt)("p",null,"Your output will look like:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-console"},'{\n "name": "w1",\n "warning": ""\n}\n')),(0,l.kt)("h3",{id:"-start-generating-blocks"},"\ud83c\udfac Start generating blocks"),(0,l.kt)("p",null,"Now, generate a new address and mine 101 blocks:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export COINBASE=$(bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getnewaddress)\nbitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass generatetoaddress 101 $COINBASE\n")),(0,l.kt)("p",null,"Next, we'll mine a block every second."),(0,l.kt)("p",null,"Add this script and remember where you placed it, I am putting it in my root directory:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-shell"},'# Script to generate a new block every second\n# Put this script at the root of your unpacked folder\n#!/bin/bash\n\necho "Generating a block every second. Press [CTRL+C] to stop.."\n\naddress=`bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getnewaddress`\n\nwhile :\ndo\n echo "Generate a new block `date \'+%d/%m/%Y %H:%M:%S\'`"\n bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass generatetoaddress 1 $address\n sleep 1\ndone\n')),(0,l.kt)("p",null,"Run the following from where you placed your ",(0,l.kt)("inlineCode",{parentName:"p"},"start.sh")," script.\nStart generating blocks by running:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bash start.sh\n")),(0,l.kt)("h4",{id:"-block-height"},"\ud83e\uddca Block height"),(0,l.kt)("p",null,"Check the current block height:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getblockcount\n")),(0,l.kt)("p",null,"Your output will look similar to below:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"4980\n")),(0,l.kt)("p",null,"Set a variable for the common flags being used:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'export FLAGS="-regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass"\n')),(0,l.kt)("h4",{id:"-block-hash"},"\ud83e\uddca Block hash"),(0,l.kt)("p",null,"Check the latest block hash:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli $FLAGS getblockhash 4980\n")),(0,l.kt)("p",null,"Your output will be the block hash of the height you first queried:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"1d7e98aec3085b615c7c71659768fa42e774a87ab5981597e99794d240fb3db5\n")),(0,l.kt)("p",null,"Set the block hash as a variable:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export HASH=1d7e98aec3085b615c7c71659768fa42e774a87ab5981597e99794d240fb3db5\n")),(0,l.kt)("h4",{id:"-block-header"},"\ud83e\uddca Block header"),(0,l.kt)("p",null,"Now to get the block header, run the following command (be sure to replace the hash with yours):"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli $FLAGS getblockheader $HASH\n")),(0,l.kt)("p",null,"Now to finish the exercise, query the height from the block header and the hash:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bitcoin-core.cli $FLAGS getblockheader $HASH | jq '.height'\n")),(0,l.kt)("h4",{id:"-restarting-the-local-network"},"\ud83c\udfac Restarting the local network"),(0,l.kt)("p",null,"In the case that you are starting your regtest network again, you can use the following command to clear the old chain history:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"rm -rf ${LOCATION OF .bitcoin folder}\n")),(0,l.kt)("h2",{id:"\ufe0f-running-the-ethermint-rollup"},"\ud83c\udfc3\u200d\u2640\ufe0f Running the Ethermint rollup"),(0,l.kt)("p",null,"Clone Ethermint:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"git clone https://github.com/celestiaorg/ethermint.git\ncd ethermint\ngit checkout bitcoin-da\nmake install\n")),(0,l.kt)("p",null,"Initialize the chain:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"bash init.sh\n")),(0,l.kt)("p",null,"Set variables for starting the chain:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export NAMESPACE_ID=$(openssl rand -hex 8)\n")),(0,l.kt)("p",null,"Start the chain:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'ethermintd start --rollkit.aggregator true --rollkit.da_layer bitcoin --rollkit.da_config=\'{"host":"127.0.0.1:18332","user":"rpcuser","pass":"rpcpass","http_post_mode":true,"disable_tls":true}\' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height 1\n')),(0,l.kt)("p",null,"Congratulations! Now that you have your Ethermint and Bitcoin rollup running, you're ready to deploy some smart contracts to the EVM!"),(0,l.kt)("h3",{id:"\ufe0f-initialize-development-environment"},"\u26a1\ufe0f Initialize development environment"),(0,l.kt)("p",null,"First, be sure you have\n",(0,l.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/getting-started/installation.html"},"installed Foundry"),"\non your local development environment."),(0,l.kt)("p",null,"Next, create a new project and change into the directory:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"forge init bitcoin-ethermint-app\ncd bitcoin-ethermint-app\n")),(0,l.kt)("p",null,"Foundry has created an example smart contract located at ",(0,l.kt)("inlineCode",{parentName:"p"},"src/Counter.sol"),"."),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"We will run the commands for the Foundry portion of this\ntutorial in the ",(0,l.kt)("inlineCode",{parentName:"p"},"~/bitcoin-ethermint-app/")," directory.")),(0,l.kt)("h3",{id:"-updating-the-contract-and-tests"},"\ud83d\udcd2 Updating the contract and tests"),(0,l.kt)("p",null,"Let's update the contracts to include a basic counter example. Open the\n",(0,l.kt)("inlineCode",{parentName:"p"},"Counter.sol")," file in the ",(0,l.kt)("inlineCode",{parentName:"p"},"src")," directory and add the following code:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-solidity"},"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ncontract Counter {\n int private count;\n \n constructor(int _count) {\n count = _count;\n }\n\n function incrementCounter() public {\n count += 1;\n }\n function decrementCounter() public {\n count -= 1;\n }\n\n function getCount() public view returns (int) {\n return count;\n }\n}\n")),(0,l.kt)("p",null,"Next, let's create a test for this contract."),(0,l.kt)("p",null,"Open ",(0,l.kt)("inlineCode",{parentName:"p"},"test/Counter.T.Sol")," and update the code with the following:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-solidity"},"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport \"forge-std/Test.sol\";\nimport 'src/Counter.sol';\n\ncontract CounterTest is Test {\n Counter counter;\n function setUp() public {\n counter = new Counter(10);\n }\n\n function testGetCount() public {\n int value = counter.getCount();\n assertEq(value, 10);\n emit log_int(value);\n }\n\n function testIncrement() public {\n counter.incrementCounter();\n counter.incrementCounter();\n int value = counter.getCount();\n assertEq(value, 12);\n emit log_int(value);\n }\n\n function testDecrement() public {\n counter.decrementCounter();\n int value = counter.getCount();\n assertEq(value, 9);\n emit log_int(value);\n }\n}\n")),(0,l.kt)("p",null,"Foundry uses ",(0,l.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/reference/ds-test.html"},"Dappsys Test")," to\nprovide basic logging and assertion functionality. It's included in the Forge\nStandard Library."),(0,l.kt)("p",null,"Here, we are using ",(0,l.kt)("inlineCode",{parentName:"p"},"assertEq")," to assert equality. You can view all of the assertion\nfunctions available\n",(0,l.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/reference/ds-test.html?highlight=log_int#asserting"},"here"),"."),(0,l.kt)("p",null,"Next, we can test the contract using ",(0,l.kt)("strong",{parentName:"p"},"Forge")," with the following command:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"forge test -vv\n")),(0,l.kt)("p",null,"A successful test will have output similar to the following:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"[\u280a] Compiling...\n[\u2830] Installing solc version 0.8.17\n[\u2812] Successfully installed solc 0.8.17\n[\u2806] Compiling 18 files with 0.8.17\n[\u2811] Solc 0.8.17 finished in 3.59s\nCompiler run successful\n\nRunning 3 tests for test/Counter.t.sol:ContractTest\n[PASS] testDecrement() (gas: 12350)\nLogs:\n 9\n\n[PASS] testGetCount() (gas: 8510)\nLogs:\n 10\n\n[PASS] testIncrement() (gas: 13285)\nLogs:\n 12\n\nTest result: ok. 3 passed; 0 failed; finished in 2.24ms\n")),(0,l.kt)("h3",{id:"-updating-the-deployment-script"},"\ud83d\udcdc Updating the deployment script"),(0,l.kt)("p",null,"Now that we've tested the contract, let's try deploying it locally using\n",(0,l.kt)("a",{parentName:"p",href:"https://book.getfoundry.sh/tutorials/solidity-scripting.html"},"Solidity Scripting"),"."),(0,l.kt)("p",null,"To do so, update the deloyment script at ",(0,l.kt)("inlineCode",{parentName:"p"},"script/Counter.s.sol")," with the\nfollowing code:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-solidity"},'// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport "forge-std/Script.sol";\n\nimport {Counter} from "src/Counter.sol";\n\ncontract CounterScript is Script {\n function setUp() public {}\n\n function run() public {\n vm.startBroadcast();\n new Counter(10);\n vm.stopBroadcast();\n }\n}\n')),(0,l.kt)("p",null,"Now we can use this script to deploy our smart contract to either a live or\ntest network."),(0,l.kt)("h3",{id:"-deploying-locally"},"\ud83c\udfe0 Deploying locally"),(0,l.kt)("p",null,"Next start Anvil, the local testnet:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"anvil --port 9545\n")),(0,l.kt)("p",null,"Once started, Anvil will give you a local RPC endpoint as well as a handful\nof Private Keys and Accounts that you can use."),(0,l.kt)("p",null,"Set ",(0,l.kt)("inlineCode",{parentName:"p"},"ANVIL_KEY")," with one of the private keys generated by running:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export ANVIL_KEY=<anvil-private-key>\n")),(0,l.kt)("p",null,"And set the RPC URL as an environment variable:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export RPC_URL=http://127.0.0.1:9545\n")),(0,l.kt)("p",null,"We can now use the local RPC along with one of the private keys to deploy locally:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"forge script script/Counter.s.sol:CounterScript --fork-url \\\n$RPC_URL --private-key $ANVIL_KEY --broadcast\n")),(0,l.kt)("p",null,"Once the contract has been deployed locally, Anvil will log out the contract address."),(0,l.kt)("p",null,"Next, set the contract address as an environment variable:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export CONTRACT_ADDRESS=<contract-address>\n")),(0,l.kt)("p",null,"We can then test sending transactions to it with ",(0,l.kt)("inlineCode",{parentName:"p"},"cast send"),"."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'cast send $CONTRACT_ADDRESS "incrementCounter()" \\\n--private-key $ANVIL_KEY --rpc-url $RPC_URL\n')),(0,l.kt)("p",null,"We can then perform read operations with ",(0,l.kt)("inlineCode",{parentName:"p"},"cast call"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url $RPC_URL\n')),(0,l.kt)("h3",{id:"-deploying-to-the-ethermint-sovereign-rollup"},"\ud83e\uddea Deploying to the Ethermint sovereign rollup"),(0,l.kt)("p",null,"Now that we've deployed and tested locally, we can deploy to our\nEthermint chain."),(0,l.kt)("p",null,"First, we will need to export the private key generated by\nthe ethermint ",(0,l.kt)("inlineCode",{parentName:"p"},"init.sh")," script:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"PRIVATE_KEY=$(ethermintd keys unsafe-export-eth-key mykey --keyring-backend test)\n")),(0,l.kt)("blockquote",null,(0,l.kt)("p",{parentName:"blockquote"},"NOTE: Here, the key name from ",(0,l.kt)("inlineCode",{parentName:"p"},"init.sh")," is ",(0,l.kt)("inlineCode",{parentName:"p"},"mykey")," but you can modify\nthe ",(0,l.kt)("inlineCode",{parentName:"p"},"init.sh")," to change the name of your key.")),(0,l.kt)("p",null,"Now, we can start deploying the smart contract to our Ethermint chain."),(0,l.kt)("p",null,"To do so, run the following script:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"forge script script/Counter.s.sol:CounterScript \\\n--rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast\n")),(0,l.kt)("p",null,"Set the contract address in the output as the ",(0,l.kt)("inlineCode",{parentName:"p"},"CONTRACT_ADDRESS")," variable:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},"export CONTRACT_ADDRESS=<new-contract-address>\n")),(0,l.kt)("p",null,"Once the contract has been deployed to the Ethermint rollup, we can\nuse ",(0,l.kt)("inlineCode",{parentName:"p"},"cast send")," to test sending transactions to it:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'cast send $CONTRACT_ADDRESS "incrementCounter()" \\\n--rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY \n')),(0,l.kt)("p",null,"We can then perform read operations with ",(0,l.kt)("inlineCode",{parentName:"p"},"cast call"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-bash"},'cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url http://127.0.0.1:8545\n')))}u.isMDXComponent=!0},2626:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/9e4087bc.ded25007.js b/pr-preview/pr-192/assets/js/9e4087bc.ded25007.js deleted file mode 100644 index 887f91fc6..000000000 --- a/pr-preview/pr-192/assets/js/9e4087bc.ded25007.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3608],{3169:(e,t,a)=>{a.r(t),a.d(t,{default:()=>o});var r=a(7294),l=a(9960),n=a(5999),c=a(1944),m=a(7676);function s(e){let{year:t,posts:a}=e;return r.createElement(r.Fragment,null,r.createElement("h3",null,t),r.createElement("ul",null,a.map((e=>r.createElement("li",{key:e.metadata.date},r.createElement(l.Z,{to:e.metadata.permalink},e.metadata.formattedDate," - ",e.metadata.title))))))}function i(e){let{years:t}=e;return r.createElement("section",{className:"margin-vert--lg"},r.createElement("div",{className:"container"},r.createElement("div",{className:"row"},t.map(((e,t)=>r.createElement("div",{key:t,className:"col col--4 margin-vert--lg"},r.createElement(s,e)))))))}function o(e){let{archive:t}=e;const a=(0,n.I)({id:"theme.blog.archive.title",message:"Archive",description:"The page & hero title of the blog archive page"}),l=(0,n.I)({id:"theme.blog.archive.description",message:"Archive",description:"The page & hero description of the blog archive page"}),s=function(e){const t=e.reduceRight(((e,t)=>{const a=t.metadata.date.split("-")[0],r=e.get(a)??[];return e.set(a,[t,...r])}),new Map);return Array.from(t,(e=>{let[t,a]=e;return{year:t,posts:a}}))}(t.blogPosts);return r.createElement(r.Fragment,null,r.createElement(c.d,{title:a,description:l}),r.createElement(m.Z,null,r.createElement("header",{className:"hero hero--primary"},r.createElement("div",{className:"container"},r.createElement("h1",{className:"hero__title"},a),r.createElement("p",{className:"hero__subtitle"},l))),r.createElement("main",null,s.length>0&&r.createElement(i,{years:s}))))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/a6aa9e1f.845cad8c.js b/pr-preview/pr-192/assets/js/a6aa9e1f.845cad8c.js deleted file mode 100644 index f3e589984..000000000 --- a/pr-preview/pr-192/assets/js/a6aa9e1f.845cad8c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3089],{46:(e,t,a)=>{a.r(t),a.d(t,{default:()=>u});var n=a(7294),l=a(6010),r=a(2263),i=a(1944),o=a(5281),s=a(9058),c=a(9703),m=a(197),g=a(9985);function p(e){const{metadata:t}=e,{siteConfig:{title:a}}=(0,r.Z)(),{blogDescription:l,blogTitle:o,permalink:s}=t,c="/"===s?a:o;return n.createElement(n.Fragment,null,n.createElement(i.d,{title:c,description:l}),n.createElement(m.Z,{tag:"blog_posts_list"}))}function d(e){const{metadata:t,items:a,sidebar:l}=e;return n.createElement(s.Z,{sidebar:l},n.createElement(g.Z,{items:a}),n.createElement(c.Z,{metadata:t}))}function u(e){return n.createElement(i.FG,{className:(0,l.Z)(o.k.wrapper.blogPages,o.k.page.blogListPage)},n.createElement(p,e),n.createElement(d,e))}},9703:(e,t,a)=>{a.d(t,{Z:()=>i});var n=a(7294),l=a(5999),r=a(2244);function i(e){const{metadata:t}=e,{previousPage:a,nextPage:i}=t;return n.createElement("nav",{className:"pagination-nav","aria-label":(0,l.I)({id:"theme.blog.paginator.navAriaLabel",message:"Blog list page navigation",description:"The ARIA label for the blog pagination"})},a&&n.createElement(r.Z,{permalink:a,title:n.createElement(l.Z,{id:"theme.blog.paginator.newerEntries",description:"The label used to navigate to the newer blog posts page (previous page)"},"Newer Entries")}),i&&n.createElement(r.Z,{permalink:i,title:n.createElement(l.Z,{id:"theme.blog.paginator.olderEntries",description:"The label used to navigate to the older blog posts page (next page)"},"Older Entries"),isNext:!0}))}},9985:(e,t,a)=>{a.d(t,{Z:()=>i});var n=a(7294),l=a(9460),r=a(390);function i(e){let{items:t,component:a=r.Z}=e;return n.createElement(n.Fragment,null,t.map((e=>{let{content:t}=e;return n.createElement(l.n,{key:t.metadata.permalink,content:t},n.createElement(a,null,n.createElement(t,null)))})))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/a7434565.8a3a8041.js b/pr-preview/pr-192/assets/js/a7434565.8a3a8041.js deleted file mode 100644 index ec70f6228..000000000 --- a/pr-preview/pr-192/assets/js/a7434565.8a3a8041.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7645],{5745:s=>{s.exports=JSON.parse('{"name":"docusaurus-plugin-content-pages","id":"default"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/b7833b35.fbe5f020.js b/pr-preview/pr-192/assets/js/b7833b35.fbe5f020.js deleted file mode 100644 index d27d305ad..000000000 --- a/pr-preview/pr-192/assets/js/b7833b35.fbe5f020.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7164],{5680:e=>{e.exports=JSON.parse('{"permalink":"/pr-preview/pr-192/blog/tags/bitcoin","page":1,"postsPerPage":10,"totalPages":1,"totalCount":1,"blogDescription":"Blog","blogTitle":"Blog"}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/be631169.f4545f2b.js b/pr-preview/pr-192/assets/js/be631169.f4545f2b.js deleted file mode 100644 index 7f0ab5da5..000000000 --- a/pr-preview/pr-192/assets/js/be631169.f4545f2b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8235],{3905:(e,t,n)=>{n.d(t,{Zo:()=>l,kt:()=>m});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,i=function(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var p=r.createContext({}),c=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},l=function(e){var t=c(e.components);return r.createElement(p.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,o=e.originalType,p=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),d=c(n),g=i,m=d["".concat(p,".").concat(g)]||d[g]||u[g]||o;return n?r.createElement(m,a(a({ref:t},l),{},{components:n})):r.createElement(m,a({ref:t},l))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=n.length,a=new Array(o);a[0]=g;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s[d]="string"==typeof e?e:i,a[1]=s;for(var c=2;c<o;c++)a[c]=n[c];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}g.displayName="MDXCreateElement"},18:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var r=n(7462),i=(n(7294),n(3905));const o={sidebar_label:"Recipe book tutorial",description:"Build a recipe book rollup with Ignite CLI, Celestia, and Rollkit"},a="\ud83e\udd57 Recipe book rollup",s={unversionedId:"tutorials/recipe-book",id:"tutorials/recipe-book",title:"\ud83e\udd57 Recipe book rollup",description:"Build a recipe book rollup with Ignite CLI, Celestia, and Rollkit",source:"@site/docs/tutorials/recipe-book.md",sourceDirName:"tutorials",slug:"/tutorials/recipe-book",permalink:"/pr-preview/pr-192/docs/tutorials/recipe-book",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/recipe-book.md",tags:[],version:"current",frontMatter:{sidebar_label:"Recipe book tutorial",description:"Build a recipe book rollup with Ignite CLI, Celestia, and Rollkit"},sidebar:"docs",previous:{title:"GM world frontend tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world-frontend"},next:{title:"How to restart your rollup",permalink:"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup"}},p={},c=[{value:"\ud83d\udcd6 Overview",id:"-overview",level:2},{value:"\ud83d\udcbb Prerequisites",id:"-prerequisites",level:2},{value:"\ud83c\udfd7\xa0Scaffolding your rollup",id:"scaffolding-your-rollup",level:2},{value:"\ud83d\udd25 Use Ignite CLI to scaffold a <code>recipes</code> rollup",id:"-use-ignite-cli-to-scaffold-a-recipes-rollup",level:3},{value:"\ud83d\udc8e Installing Rollkit",id:"-installing-rollkit",level:3},{value:"\ud83d\udcac\xa0Message types",id:"message-types",level:2},{value:"\u2728\xa0Create message types",id:"create-message-types",level:3},{value:"\ud83e\udd3f\xa0Diving deeper into the message code",id:"diving-deeper-into-the-message-code",level:4},{value:"\ud83d\udcd5\xa0Define messages logic",id:"define-messages-logic",level:3},{value:"\ud83d\udd01 Keepers",id:"-keepers",level:2},{value:"\ud83d\udcd7\xa0Define <code>Recipe</code> type and <code>AppendRecipe</code> keeper method",id:"define-recipe-type-and-appendrecipe-keeper-method",level:3},{value:"\ud83d\udcd8\xa0Define keeper methods",id:"define-keeper-methods",level:3},{value:"\ud83c\udf7d\ufe0f\xa0Querying recipes",id:"\ufe0fquerying-recipes",level:2},{value:"\ud83d\udda5 Query recipes",id:"-query-recipes",level:3},{value:"\ud83d\udc69\u200d\ud83c\udf73 Running the recipes rollup",id:"-running-the-recipes-rollup",level:2},{value:"\u2728 Run a Celestia light node",id:"-run-a-celestia-light-node",level:3},{value:"\ud83d\uddde\ufe0f Start the recipes rollup",id:"\ufe0f-start-the-recipes-rollup",level:3},{value:"\u2328\ufe0f\xa0Query your recipes with the CLI",id:"\ufe0fquery-your-recipes-with-the-cli",level:3}],l={toc:c};function d(e){let{components:t,...o}=e;return(0,i.kt)("wrapper",(0,r.Z)({},l,o,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"-recipe-book-rollup"},"\ud83e\udd57 Recipe book rollup"),(0,i.kt)("h2",{id:"-overview"},"\ud83d\udcd6 Overview"),(0,i.kt)("p",null,"In this tutorial, we are going to build a blockchain\nfor your favorite recipes. The goal of this tutorial\nis to create a Rollkit rollup with a module that allows\nyou to write and read data to and from your application-specific\nblockchain. The end user will be able to submit new\nrecipes and read them from the blockchain."),(0,i.kt)("p",null,"In the ",(0,i.kt)("a",{parentName:"p",href:"/pr-preview/pr-192/docs/tutorials/gm-world"},(0,i.kt)("inlineCode",{parentName:"a"},"GM World")," tutorial"),", we defined a\nnew API endpoint and modified a keeper query function\nto return static data. In this tutorial, we will be\nmodifying the state with transactions (Cosmos SDK messages)\nthat are routed to a module and its message handlers, which\nare sent to the ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes")," blockchain."),(0,i.kt)("admonition",{title:"note",type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"This tutorial will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"Issue ticket"),"\nor let us know in our ",(0,i.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),".")),(0,i.kt)("admonition",{title:"caution",type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"The script for this tutorial is built for Celestia's\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspacerace testnet"),".\nIf you choose to use Mocha testnet or Arabica devnet,\nyou will need to modify the script manually.")),(0,i.kt)("h2",{id:"-prerequisites"},"\ud83d\udcbb Prerequisites"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/gm-world"},"GM World Tutorial"))),(0,i.kt)("h2",{id:"scaffolding-your-rollup"},"\ud83c\udfd7\xa0Scaffolding your rollup"),(0,i.kt)("h3",{id:"-use-ignite-cli-to-scaffold-a-recipes-rollup"},"\ud83d\udd25 Use Ignite CLI to scaffold a ",(0,i.kt)("inlineCode",{parentName:"h3"},"recipes")," rollup"),(0,i.kt)("p",null,"Run the following command to scaffold your ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes")," chain using Ignite CLI:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold chain recipes --address-prefix recipes\n")),(0,i.kt)("p",null,"Your new ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes")," chain has been scaffolded and\n",(0,i.kt)("inlineCode",{parentName:"p"},"--address-prefix recipes")," allows the address prefix\nto be ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes")," instead of ",(0,i.kt)("inlineCode",{parentName:"p"},"cosmos"),"."),(0,i.kt)("p",null,"Change into the ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes")," directory:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"cd recipes\n")),(0,i.kt)("h3",{id:"-installing-rollkit"},"\ud83d\udc8e Installing Rollkit"),(0,i.kt)("p",null,"To swap out Tendermint for Rollkit, run the following commands:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs\ngo mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d\ngo mod tidy\ngo mod download\n")),(0,i.kt)("h2",{id:"message-types"},"\ud83d\udcac\xa0Message types"),(0,i.kt)("h3",{id:"create-message-types"},"\u2728\xa0Create message types"),(0,i.kt)("p",null,"Create a message type and its handler with the ",(0,i.kt)("inlineCode",{parentName:"p"},"message")," command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold message createRecipe dish ingredients\n")),(0,i.kt)("p",null,"Response:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"modify proto/recipes/recipes/tx.proto\nmodify x/recipes/client/cli/tx.go\ncreate x/recipes/client/cli/tx_create_recipe.go\ncreate x/recipes/keeper/msg_server_create_recipe.go\nmodify x/recipes/module_simulation.go\ncreate x/recipes/simulation/create_recipe.go\nmodify x/recipes/types/codec.go\ncreate x/recipes/types/message_create_recipe.go\ncreate x/recipes/types/message_create_recipe_test.go\n\n\ud83c\udf89 Created a message `createRecipe`.\n")),(0,i.kt)("p",null,"Head to your ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/proto/recipes/recipes/tx.proto")," file\nand you will see the ",(0,i.kt)("inlineCode",{parentName:"p"},"MsgCreateRecipe")," has been created.\nAdd ",(0,i.kt)("inlineCode",{parentName:"p"},"uint64 id = 1;")," to the ",(0,i.kt)("inlineCode",{parentName:"p"},"MsgCreateRecipeResponse")," function:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="recipes/proto/recipes/recipes/tx.proto"',title:'"recipes/proto/recipes/recipes/tx.proto"'},"message MsgCreateRecipeResponse {\n uint64 id = 1;\n}\n")),(0,i.kt)("h4",{id:"diving-deeper-into-the-message-code"},"\ud83e\udd3f\xa0Diving deeper into the message code"),(0,i.kt)("p",null,"Looking further into the message, we can see that\n",(0,i.kt)("inlineCode",{parentName:"p"},"MsgCreateRecipe")," has 3 fields: creator, dish, and ingredients."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="recipes/proto/recipes/recipes/tx.proto"',title:'"recipes/proto/recipes/recipes/tx.proto"'},"message MsgCreateRecipe {\n string creator = 1;\n string dish = 2;\n string ingredients = 3;\n}\n")),(0,i.kt)("p",null,"We can also see that the ",(0,i.kt)("inlineCode",{parentName:"p"},"CreateRecipe")," RPC has already been added to the ",(0,i.kt)("inlineCode",{parentName:"p"},"Msg")," service:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="recipes/proto/recipes/recipes/tx.proto"',title:'"recipes/proto/recipes/recipes/tx.proto"'},"service Msg {\n rpc CreateRecipe(MsgCreateRecipe) returns (MsgCreateRecipeResponse);\n}\n")),(0,i.kt)("h3",{id:"define-messages-logic"},"\ud83d\udcd5\xa0Define messages logic"),(0,i.kt)("p",null,"Navigate to ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/x/recipes/keeper/msg_server_create_recipe.go"),".\nFor our recipes chain, we want the dish and ingredients to be written\nto the blockchain\u2019s state as a new recipe. Add the following code to\nthe ",(0,i.kt)("inlineCode",{parentName:"p"},"CreateRecipe")," function underneath the imports:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/msg_server_create_recipe.go"',title:'"recipes/x/recipes/keeper/msg_server_create_recipe.go"'},"func (k msgServer) CreateRecipe(goCtx context.Context, msg *types.MsgCreateRecipe) (*types.MsgCreateRecipeResponse, error) {\n // Get the context\n ctx := sdk.UnwrapSDKContext(goCtx)\n\n // Create variable of type Recipe\n var recipe = types.Recipe{\n Creator: msg.Creator,\n Dish: msg.Dish,\n Ingredients: msg.Ingredients,\n }\n\n // Add a recipe to the store and get back the ID\n id := k.AppendRecipe(ctx, recipe)\n\n // Return the ID of the recipe\n return &types.MsgCreateRecipeResponse{Id: id}, nil\n}\n")),(0,i.kt)("p",null,"You will see errors in your text editor, which we will resolve in the next step."),(0,i.kt)("h2",{id:"-keepers"},"\ud83d\udd01 Keepers"),(0,i.kt)("h3",{id:"define-recipe-type-and-appendrecipe-keeper-method"},"\ud83d\udcd7\xa0Define ",(0,i.kt)("inlineCode",{parentName:"h3"},"Recipe")," type and ",(0,i.kt)("inlineCode",{parentName:"h3"},"AppendRecipe")," keeper method"),(0,i.kt)("p",null,"Create a file ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/proto/recipes/recipes/recipe.proto")," and\ndefine the ",(0,i.kt)("inlineCode",{parentName:"p"},"Recipe")," message:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/proto/recipes/recipes/recipe.proto"',title:'"recipes/proto/recipes/recipes/recipe.proto"'},'syntax = "proto3";\n\npackage recipes.recipes;\n\noption go_package = "recipes/x/recipes/types";\n\nmessage Recipe {\n string creator = 1;\n uint64 id = 2;\n string dish = 3; \n string ingredients = 4; \n}\n')),(0,i.kt)("h3",{id:"define-keeper-methods"},"\ud83d\udcd8\xa0Define keeper methods"),(0,i.kt)("p",null,"Now you\u2019ll define your ",(0,i.kt)("inlineCode",{parentName:"p"},"AppendRecipe")," keeper method."),(0,i.kt)("p",null,"Create the ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/x/recipes/keeper/recipe.go")," file. The\n",(0,i.kt)("inlineCode",{parentName:"p"},"AppendRecipe")," function is a placeholder to brainstorm how\nto implement it:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/recipe.go"',title:'"recipes/x/recipes/keeper/recipe.go"'},'package keeper\n\nimport (\n "encoding/binary"\n\n "github.com/cosmos/cosmos-sdk/store/prefix"\n sdk "github.com/cosmos/cosmos-sdk/types"\n\n "recipes/x/recipes/types"\n)\n\n// func (k Keeper) AppendRecipe() uint64 {\n// count := k.GetRecipeCount()\n// store.Set()\n// k.SetRecipeCount()\n// return count\n// }\n')),(0,i.kt)("p",null,"Add these prefixes to the ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/x/recipes/types/keys.go")," file\nin the ",(0,i.kt)("inlineCode",{parentName:"p"},"const")," and add a comment for your reference:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/types/keys.go"',title:'"recipes/x/recipes/types/keys.go"'},'const (\n //...\n\n // Keep track of the index of recipes \n RecipeKey = "Recipe-value-"\n RecipeCountKey = "Recipe-count-"\n)\n')),(0,i.kt)("p",null,"Next, implement ",(0,i.kt)("inlineCode",{parentName:"p"},"GetRecipeCount")," in the ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/x/recipes/keeper/recipe.go")," file:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/recipe.go"',title:'"recipes/x/recipes/keeper/recipe.go"'},'func (k Keeper) GetRecipeCount(ctx sdk.Context) uint64 {\n // Get the store using storeKey (which is "recipes") and RecipeCountKey (which is "Recipe-count-")\n store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeCountKey))\n \n // Convert the RecipeCountKey to bytes\n byteKey := []byte(types.RecipeCountKey)\n \n // Get the value of the count\n bz := store.Get(byteKey)\n \n // Return zero if the count value is not found (for example, it\'s the first recipe)\n if bz == nil {\n return 0\n }\n \n // Convert the count into a uint64\n return binary.BigEndian.Uint64(bz)\n}\n')),(0,i.kt)("p",null,"And then ",(0,i.kt)("inlineCode",{parentName:"p"},"SetRecipeCount"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/recipe.go"',title:'"recipes/x/recipes/keeper/recipe.go"'},'func (k Keeper) SetRecipeCount(ctx sdk.Context, count uint64) {\n // Get the store using storeKey (which is "recipes") and RecipeCountKey (which is "Recipe-count-")\n store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeCountKey))\n \n // Convert the RecipeCountKey to bytes\n byteKey := []byte(types.RecipeCountKey)\n \n // Convert count from uint64 to string and get bytes\n bz := make([]byte, 8)\n binary.BigEndian.PutUint64(bz, count)\n \n // Set the value of Recipe-count- to count\n store.Set(byteKey, bz)\n}\n')),(0,i.kt)("p",null,"Now you\u2019re ready to implement the ",(0,i.kt)("inlineCode",{parentName:"p"},"AppendRecipe")," function at\nthe top of the file above ",(0,i.kt)("inlineCode",{parentName:"p"},"GetRecipeCount")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"SetRecipeCount"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/recipe.go"',title:'"recipes/x/recipes/keeper/recipe.go"'},"func (k Keeper) AppendRecipe (ctx sdk.Context, recipe types.Recipe) uint64 {\n // Get the current number of recipes in the store\n count := k.GetRecipeCount(ctx)\n \n // Assign an ID to the recipe based on the number of recipes in the store\n recipe.Id = count\n \n // Get the store\n store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeKey))\n \n // Convert the recipe ID into bytes\n byteKey := make([]byte, 8)\n binary.BigEndian.PutUint64(byteKey, recipe.Id)\n \n // Marshal the recipe into bytes\n appendedValue := k.cdc.MustMarshal(&recipe)\n \n // Insert the recipe bytes using recipe ID as a key\n store.Set(byteKey, appendedValue)\n \n // Update the recipe count\n k.SetRecipeCount(ctx, count+1)\n return count\n}\n")),(0,i.kt)("p",null,"Now you have implemented all the code required to create\nnew recipes and store them on-chain. When a transaction that\ncontains a message type ",(0,i.kt)("inlineCode",{parentName:"p"},"MsgCreateRecipe")," is broadcast, the\nmessage is routed to the recipes module."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"k.CreateRecipe")," calls ",(0,i.kt)("inlineCode",{parentName:"li"},"AppendRecipe"),", which gets the recipe\ncount, adds a recipe using the count as the ID, increments the\ncount, and returns the ID")),(0,i.kt)("h2",{id:"\ufe0fquerying-recipes"},"\ud83c\udf7d\ufe0f\xa0Querying recipes"),(0,i.kt)("h3",{id:"-query-recipes"},"\ud83d\udda5 Query recipes"),(0,i.kt)("p",null,"In order to query your recipes, scaffold a query with Ignite:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold query dishes --response dish,ingredients\n")),(0,i.kt)("p",null,"A response on a successful scaffold will look like this:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"modify proto/recipes/recipes/query.proto\nmodify x/recipes/client/cli/query.go\ncreate x/recipes/client/cli/query_dishes.go\ncreate x/recipes/keeper/query_dishes.go\n\n\ud83c\udf89 Created a query `dishes`.\n")),(0,i.kt)("p",null,"In the ",(0,i.kt)("inlineCode",{parentName:"p"},"proto/recipes/recipes/query.proto")," file import:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="proto/recipes/recipes/query.proto"',title:'"proto/recipes/recipes/query.proto"'},'import "recipes/recipes/recipe.proto";\n')),(0,i.kt)("p",null,"Add pagination to the recipe ",(0,i.kt)("em",{parentName:"p"},"request"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="proto/recipes/recipes/query.proto"',title:'"proto/recipes/recipes/query.proto"'},"message QueryDishesRequest {\n // Adding pagination to request\n cosmos.base.query.v1beta1.PageRequest pagination = 1;\n}\n")),(0,i.kt)("p",null,"Add pagination to the recipe ",(0,i.kt)("em",{parentName:"p"},"response"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-protobuf",metastring:'title="proto/recipes/recipes/query.proto"',title:'"proto/recipes/recipes/query.proto"'},"message QueryDishesResponse {\n // Returning a list of recipes\n repeated Recipe Recipe = 1;\n\n // Adding pagination to response\n cosmos.base.query.v1beta1.PageResponse pagination = 2;\n}\n")),(0,i.kt)("p",null,"In order to implement recipe querying logic in\n",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/x/recipes/keeper/query_dishes.go"),",\ndelete the file contents and replace them with:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/x/recipes/keeper/query_dishes.go"',title:'"recipes/x/recipes/keeper/query_dishes.go"'},'package keeper\n\nimport (\n "context"\n "github.com/cosmos/cosmos-sdk/store/prefix"\n sdk "github.com/cosmos/cosmos-sdk/types"\n "github.com/cosmos/cosmos-sdk/types/query"\n "google.golang.org/grpc/codes"\n "google.golang.org/grpc/status"\n\n "recipes/x/recipes/types"\n)\n\nfunc (k Keeper) Dishes(c context.Context, req *types.QueryDishesRequest) (*types.QueryDishesResponse, error) {\n // Throw an error if request is nil\n if req == nil {\n return nil, status.Error(codes.InvalidArgument, "invalid request")\n }\n\n // Define a variable that will store a list of recipes\n var dishes []*types.Recipe\n\n // Get context with the information about the environment\n ctx := sdk.UnwrapSDKContext(c)\n\n // Get the key-value module store using the store key (in our case store key is "chain")\n store := ctx.KVStore(k.storeKey)\n\n // Get the part of the store that keeps recipes (using recipe key, which is "Recipe-value-")\n recipeStore := prefix.NewStore(store, []byte(types.RecipeKey))\n\n // Paginate the recipes store based on PageRequest\n pageRes, err := query.Paginate(recipeStore, req.Pagination, func(key []byte, value []byte) error {\n var dish types.Recipe\n if err := k.cdc.Unmarshal(value, &dish); err != nil {\n return err\n }\n\n dishes = append(dishes, &dish)\n\n return nil\n })\n\n // Throw an error if pagination failed\n if err != nil {\n return nil, status.Error(codes.Internal, err.Error())\n }\n\n // Return a struct containing a list of recipes and pagination info\n return &types.QueryDishesResponse{Recipe: dishes, Pagination: pageRes}, nil\n}\n')),(0,i.kt)("h2",{id:"-running-the-recipes-rollup"},"\ud83d\udc69\u200d\ud83c\udf73 Running the recipes rollup"),(0,i.kt)("h3",{id:"-run-a-celestia-light-node"},"\u2728 Run a Celestia light node"),(0,i.kt)("p",null,"Follow instructions to install and start your Celestia Data Availalbility\nlayer Light Node selecting the network that you previously used. You can\nfind instructions to install and run the node ",(0,i.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/light-node"},"here"),"."),(0,i.kt)("p",null,"After you have Go and Ignite CLI installed, and your Celestia Light\nNode running on your machine, you're ready to build, test, and launch your own\nsovereign rollup."),(0,i.kt)("p",null,"Be sure you have initialized your node before trying to start it.\nWhen starting your node, remember to enable the gateway.\nYour start command should look similar to:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"celestia light start --core.ip https://rpc-blockspacerace.pops.one --gateway --gateway.addr 127.0.0.1 --gateway.port 26659 --p2p.network blockspacerace\n")),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"light-node.png",src:n(2218).Z,width:"1912",height:"1514"})),(0,i.kt)("h3",{id:"\ufe0f-start-the-recipes-rollup"},"\ud83d\uddde\ufe0f Start the recipes rollup"),(0,i.kt)("p",null,"We have a handy ",(0,i.kt)("inlineCode",{parentName:"p"},"init.sh")," found in this repo\n",(0,i.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/tree/main/docs/scripts/recipes"},"here"),"."),(0,i.kt)("p",null,"We can copy it over to our directory with the following commands:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"# From inside the `recipes` directory\nwget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/recipes/init.sh\n")),(0,i.kt)("p",null,"This copies over our ",(0,i.kt)("inlineCode",{parentName:"p"},"init.sh")," script to initialize our\nRecipes Rollup."),(0,i.kt)("p",null,"You can view the contents of the script to see how we\ninitialize the Recipes Rollup."),(0,i.kt)("admonition",{title:"caution",type:"danger"},(0,i.kt)("p",{parentName:"admonition"},"Before starting our rollup, we'll need to find\nand change ",(0,i.kt)("inlineCode",{parentName:"p"},"FlagDisableIAVLFastNode")," to ",(0,i.kt)("inlineCode",{parentName:"p"},"FlagIAVLFastNode"),":"),(0,i.kt)("pre",{parentName:"admonition"},(0,i.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="recipes/cmd/recipesd/cmd/root.go"',title:'"recipes/cmd/recipesd/cmd/root.go"'},"baseapp.SetIAVLFastNode(cast.ToBool(appOpts.Get(server.FlagIAVLFastNode))),\n"))),(0,i.kt)("p",null,"\ud83d\udfe2 From your project working directory (",(0,i.kt)("inlineCode",{parentName:"p"},"recipes/"),"), start the chain with:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"bash init.sh\n")),(0,i.kt)("p",null,"With that, we have kickstarted our ",(0,i.kt)("inlineCode",{parentName:"p"},"recipesd")," network!"),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"recipe-start.gif",src:n(7257).Z,width:"1888",height:"1536"})),(0,i.kt)("p",null,"Open another teminal instance. Now, create your first\nrecipe in the command line by sending a transaction from ",(0,i.kt)("inlineCode",{parentName:"p"},"recipes-key"),",\nwhen prompted, confirm the transaction by entering ",(0,i.kt)("inlineCode",{parentName:"p"},"y"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'recipesd tx recipes create-recipe salad "spinach, mandarin oranges, sliced almonds, smoked gouda, citrus vinagrette" --from recipes-key --keyring-backend test\n')),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"recipes.gif",src:n(9018).Z,width:"1410",height:"1128"})),(0,i.kt)("h3",{id:"\ufe0fquery-your-recipes-with-the-cli"},"\u2328\ufe0f\xa0Query your recipes with the CLI"),(0,i.kt)("p",null,"To query all of the on-chain recipes:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"recipesd q recipes dishes\n")),(0,i.kt)("p",null,(0,i.kt)("img",{alt:"query.gif",src:n(4862).Z,width:"1410",height:"1128"})),(0,i.kt)("p",null,"\ud83c\udf89\xa0Congratulations, again! You have now successfully built a recipe book rollup."))}d.isMDXComponent=!0},2218:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/light-node-e9bf84be9327c23a6573c247e5ede7cd.png"},4862:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/query-a6c8042342b2de67304f474de6c0df65.gif"},7257:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/recipe-start-b435769158f76024880099308cda4224.gif"},9018:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/recipes-ed8d74ded258a73a05555483e33b0c01.gif"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/c463304d.ea019477.js b/pr-preview/pr-192/assets/js/c463304d.ea019477.js deleted file mode 100644 index 751aa04c4..000000000 --- a/pr-preview/pr-192/assets/js/c463304d.ea019477.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[2193],{3905:(e,t,a)=>{a.d(t,{Zo:()=>c,kt:()=>m});var n=a(7294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?o(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):o(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function i(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},o=Object.keys(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)a=o[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var s=n.createContext({}),p=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},c=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},k=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),d=p(a),k=r,m=d["".concat(s,".").concat(k)]||d[k]||u[k]||o;return a?n.createElement(m,l(l({ref:t},c),{},{components:a})):n.createElement(m,l({ref:t},c))}));function m(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=a.length,l=new Array(o);l[0]=k;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[d]="string"==typeof e?e:r,l[1]=i;for(var p=2;p<o;p++)l[p]=a[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,a)}k.displayName="MDXCreateElement"},8793:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var n=a(7462),r=(a(7294),a(3905));const o={sidebar_label:"Rollkit stack",description:"Intro to Rollkit's stack, a modular framework for rollups."},l="The Rollkit stack",i={unversionedId:"rollkit-stack",id:"rollkit-stack",title:"The Rollkit stack",description:"Intro to Rollkit's stack, a modular framework for rollups.",source:"@site/docs/rollkit-stack.md",sourceDirName:".",slug:"/rollkit-stack",permalink:"/pr-preview/pr-192/docs/rollkit-stack",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/rollkit-stack.md",tags:[],version:"current",frontMatter:{sidebar_label:"Rollkit stack",description:"Intro to Rollkit's stack, a modular framework for rollups."},sidebar:"docs",previous:{title:"Introduction",permalink:"/pr-preview/pr-192/docs/intro"},next:{title:"Transaction flow",permalink:"/pr-preview/pr-192/docs/transaction-flow"}},s={},p=[{value:"Application structure",id:"application-structure",level:2},{value:"ABCI interface",id:"abci-interface",level:3},{value:"Cosmos SDK",id:"cosmos-sdk",level:4},{value:"Data availability",id:"data-availability",level:3},{value:"Celestia",id:"celestia",level:4},{value:"Node components",id:"node-components",level:2},{value:"Mempool",id:"mempool",level:3},{value:"Block manager",id:"block-manager",level:3},{value:"RPC",id:"rpc",level:3},{value:"P2P layer",id:"p2p-layer",level:3},{value:"Rollkit node types",id:"rollkit-node-types",level:2},{value:"Full node",id:"full-node",level:3},{value:"Light node (work in progress)",id:"light-node-work-in-progress",level:3},{value:"Sequencer node",id:"sequencer-node",level:3},{value:"State validity modes",id:"state-validity-modes",level:2},{value:"Pessimistic (full nodes only)",id:"pessimistic-full-nodes-only",level:3},{value:"Optimistic (fraud proofs) (work in progress)",id:"optimistic-fraud-proofs-work-in-progress",level:3},{value:"Validity (ZK proofs)",id:"validity-zk-proofs",level:3}],c={toc:p};function d(e){let{components:t,...o}=e;return(0,r.kt)("wrapper",(0,n.Z)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"the-rollkit-stack"},"The Rollkit stack"),(0,r.kt)("p",null,"This page will cover the main components of Rollkit."),(0,r.kt)("p",null,"Rollup sequencer nodes collect transactions from users, aggregate them into blocks, and post the blocks onto a data availability (DA) layer (such as Celestia) to be ordered and finalized. Full nodes execute and verify rollup blocks, and in the case of an optimistic rollup, propagate fraud proofs when needed. Light clients will receive headers, verify proofs (fraud, zk, etc), and authenticate trust-minimized queries about the state."),(0,r.kt)("admonition",{title:"Tip",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you're familiar with Rollkit's stack, you may want to skip to the ",(0,r.kt)("a",{parentName:"p",href:"../category/tutorials"},"tutorials section"),".")),(0,r.kt)("h2",{id:"application-structure"},"Application structure"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"Rollup architecture with Rollkit and ABCI.",src:a(3334).Z,width:"1538",height:"1127"})),(0,r.kt)("h3",{id:"abci-interface"},"ABCI interface"),(0,r.kt)("p",null,"Rollkit is a fully functional Application BlockChain Interface (ABCI) client software. It can be used as a Tendermint replacement for any ABCI application.\nThanks to this compatibility, you can use tools like ",(0,r.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/v0.34/app-dev/abci-cli.html"},"abci-cli")," to test and debug your rollup."),(0,r.kt)("h4",{id:"cosmos-sdk"},"Cosmos SDK"),(0,r.kt)("p",null,"Would you like to change your Cosmos SDK application to a Rollkit rollup?\nNo problem! You need to replace the Cosmos SDK Go dependency with a\nRollkit-enabled version, which can be found\nat the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/cosmos-sdk"},(0,r.kt)("inlineCode",{parentName:"a"},"rollkit/cosmos-sdk"))," repository."),(0,r.kt)("p",null,"Note the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/cosmos-sdk"},(0,r.kt)("inlineCode",{parentName:"a"},"rollkit/cosmos-sdk"))," repository follows the release branches of\nupstream Cosmos SDK, but with the bonus of using Rollkit instead of Tendermint\nas the ABCI client."),(0,r.kt)("p",null,"And don't forget to replace another dependency, ",(0,r.kt)("inlineCode",{parentName:"p"},"tendermint"),", with\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/tendermint"},(0,r.kt)("inlineCode",{parentName:"a"},"rollkit/tendermint")),", which has an enhanced ABCI interface that includes\nthe methods needed for state fraud proofs."),(0,r.kt)("h3",{id:"data-availability"},"Data availability"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/da"},"Data availability (DA)")," can be accessed using generic ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/main/da/da.go"},"interfaces"),". This design allows for seamless integration with any DA layer. New implementations can be plugged in programmatically, without a need to fork Rollkit."),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"DataAvailabilityLayerClient")," interface includes essential lifecycle methods (",(0,r.kt)("inlineCode",{parentName:"p"},"Init"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"Start"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"Stop"),") as well as data availability methods (",(0,r.kt)("inlineCode",{parentName:"p"},"SubmitBlock"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"CheckBlockAvailability"),")."),(0,r.kt)("p",null,"The ",(0,r.kt)("inlineCode",{parentName:"p"},"BlockRetriever")," interface serves to enable syncing of full nodes from the data availability layer.\nIt's important to keep in mind that there is no direct correlation between the DA layer block height and the rollup height. Each DA layer block may contain an arbitrary number of rollup blocks."),(0,r.kt)("h4",{id:"celestia"},"Celestia"),(0,r.kt)("p",null,"Celestia is an example of a data availability integration implemented for Rollkit.\nIt's using the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.celestia.org/developers/node-gateway-docs/"},"Celestia Node Gateway API"),"\nvia the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/go-cnc"},(0,r.kt)("inlineCode",{parentName:"a"},"celestiaorg/go-cnc"))," package.\nTo deploy a Rollkit rollup on Celestia you also have to ",(0,r.kt)("a",{parentName:"p",href:"https://docs.celestia.org/developers/node-tutorial/"},"run a Celestia light node"),"."),(0,r.kt)("h2",{id:"node-components"},"Node components"),(0,r.kt)("h3",{id:"mempool"},"Mempool"),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/mempool"},"mempool")," is inspired by the Tendermint mempool. By default, transactions are handled in a First Come, First Served (FCFS) manner. Ordering of transactions can be implemented on the application level; currently this is possible by returning a priority on ",(0,r.kt)("inlineCode",{parentName:"p"},"CheckTx"),", and once we support ABCI++ it is also possible via ",(0,r.kt)("inlineCode",{parentName:"p"},"PrepareProposal")," and the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/v0.47/building-apps/app-mempool"},"application mempool"),"."),(0,r.kt)("h3",{id:"block-manager"},"Block manager"),(0,r.kt)("p",null,"The ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/block"},"block manager")," contains Go routines ",(0,r.kt)("inlineCode",{parentName:"p"},"AggregationLoop"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"RetrieveLoop"),", and ",(0,r.kt)("inlineCode",{parentName:"p"},"SyncLoop")," that communicate through Go channels. These Go routines are ran when a Rollkit node starts up (",(0,r.kt)("inlineCode",{parentName:"p"},"OnStart"),"). Only the sequencer nodes run ",(0,r.kt)("inlineCode",{parentName:"p"},"AggregationLoop")," which controls the frequency of block production for a rollup with a timer as per the ",(0,r.kt)("inlineCode",{parentName:"p"},"BlockTime")," in ",(0,r.kt)("inlineCode",{parentName:"p"},"BlockManager"),"."),(0,r.kt)("p",null,"All nodes run ",(0,r.kt)("inlineCode",{parentName:"p"},"SyncLoop")," which looks for the following operations:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Receive block headers"),": block headers are received through a channel ",(0,r.kt)("inlineCode",{parentName:"li"},"HeaderInCh")," and Rollkit nodes attempt to verify the block with the corresponding block data."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Receive block data"),": block bodies are received through a channel ",(0,r.kt)("inlineCode",{parentName:"li"},"blockInCh")," and Rollkit nodes attempt to verify the block."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Receive state fraud proofs"),": state fraud proofs are received through a channel ",(0,r.kt)("inlineCode",{parentName:"li"},"FraudProofInCh")," and Rollkit nodes attempt to verify them. Note that we plan to make this configurable for full nodes since full nodes also produce state fraud proofs on their own."),(0,r.kt)("li",{parentName:"ul"},"Signal ",(0,r.kt)("inlineCode",{parentName:"li"},"RetrieveLoop")," with timer as per the ",(0,r.kt)("inlineCode",{parentName:"li"},"DABlockTime")," in ",(0,r.kt)("inlineCode",{parentName:"li"},"BlockManager"),".")),(0,r.kt)("p",null,"All nodes also run ",(0,r.kt)("inlineCode",{parentName:"p"},"RetrieveLoop")," which is responsible for interacting with the data availability layer. It checks the last updated ",(0,r.kt)("inlineCode",{parentName:"p"},"DAHeight")," to retrieve a block with timer ",(0,r.kt)("inlineCode",{parentName:"p"},"DABlockTime")," signaled by ",(0,r.kt)("inlineCode",{parentName:"p"},"SyncLoop"),". Note that the start height of the DA layer for the rollup, ",(0,r.kt)("inlineCode",{parentName:"p"},"DAStartHeight"),", is configurable in ",(0,r.kt)("inlineCode",{parentName:"p"},"BlockManager"),"."),(0,r.kt)("h3",{id:"rpc"},"RPC"),(0,r.kt)("p",null,"Rollkit's ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/rpc"},"RPC")," fully implements the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.tendermint.com/v0.34/rpc"},"Tendermint RPC")," interfaces and APIs for querying:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"Information about the rollup node"),": information such as node's health, status, and network info."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"The rollup blockchain"),": getting information about the rollup blockchain such as blocks and block headers."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"The rollup transactions"),": getting transaction information and broadcasting raw transactions, with search capabilities."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("strong",{parentName:"li"},"ABCI"),": rollup application information.")),(0,r.kt)("p",null,"The following RPC protocols are currently supported:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"URI over HTTP"),(0,r.kt)("li",{parentName:"ul"},"JSON-RPC over HTTP"),(0,r.kt)("li",{parentName:"ul"},"JSON-RPC over WebSockets")),(0,r.kt)("h3",{id:"p2p-layer"},"P2P layer"),(0,r.kt)("p",null,"Rollkit's ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/p2p"},"P2P layer")," enables\ndirect communication between rollup nodes.\nIt's used to gossip transactions, headers of newly created blocks, and state fraud proofs.\nThe P2P layer is implemented using ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/libp2p"},"libp2p"),"."),(0,r.kt)("p",null,"Rollkit uses ",(0,r.kt)("a",{parentName:"p",href:"https://curriculum.pl-launchpad.io/curriculum/libp2p/dht/"},"DHT-based active peer discovery"),".\nStarting a node connects to pre-configured bootstrap peers, and advertises its namespace ID in the DHT.\nThis solution is flexible, because multiple rollup networks may reuse the same DHT/bootstrap nodes,\nbut specific rollup network might decide to use dedicated nodes as well."),(0,r.kt)("h2",{id:"rollkit-node-types"},"Rollkit node types"),(0,r.kt)("p",null,"Rollkit nodes are implemented in the ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/node"},(0,r.kt)("inlineCode",{parentName:"a"},"node"))," package."),(0,r.kt)("h3",{id:"full-node"},"Full node"),(0,r.kt)("p",null,"Full nodes verify all blocks, and produce fraud proofs for optimistic rollups. Since they fully verify all rollup blocks, they don't rely on fraud or validity proofs for security."),(0,r.kt)("h3",{id:"light-node-work-in-progress"},"Light node (work in progress)"),(0,r.kt)("p",null,"Light nodes are light-weight rollup nodes that authenticate block headers, and can be secured by fraud proofs or validity proofs. They're recommended for average users on low-resource devices. Users running light nodes can make trust-minimized queries about the rollup's state. Currently, Rollkit light nodes are still under development."),(0,r.kt)("h3",{id:"sequencer-node"},"Sequencer node"),(0,r.kt)("p",null,"Rollups can utilize sequencer nodes. Sequencers are block producers for rollups, responsible for aggregating transactions into blocks, and typically executing transactions to produce a state root, used by the rollup's light clients."),(0,r.kt)("p",null,"Rollkit plans to support multiple different pluggable sequencer schemes:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:"center"}),(0,r.kt)("th",{parentName:"tr",align:"center"},"Deploy in one-click"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Faster soft-confirmations than L1"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Control over rollup's transaction ordering"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Atomic composability with other rollups"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Censorship resistance"),(0,r.kt)("th",{parentName:"tr",align:"center"},"Implementation Status"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"Centralized sequencer"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Requires spinning up a sequencer"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"No \u274c"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Eventual \u23f3*"),(0,r.kt)("td",{parentName:"tr",align:"center"},"\u2705 Implemented!")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"Decentralized sequencer"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Requires spinning up a sequencer set"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"No \u274c"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Real-time \u26a1\ufe0f"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Planned")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"Shared decentralized sequencer"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"No \u274c"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Real-time \u26a1\ufe0f"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Planned")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:"center"},"Pure fork-choice rule"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Yes \u2705"),(0,r.kt)("td",{parentName:"tr",align:"center"},"No \u274c"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Maybe \ud83d\udfe1"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Maybe \ud83d\udfe1"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Eventual \u23f3"),(0,r.kt)("td",{parentName:"tr",align:"center"},"Planned")))),(0,r.kt)("p",null,'"Pure fork-choice rule" refers to any rollup without privileged sequencers, e.g. nodes defer to the data availability layer for ordering and apply a "first-come-first-serve" fork-choice rule.'),(0,r.kt)("p",null,"*"," implementation of this property is in progress."),(0,r.kt)("h2",{id:"state-validity-modes"},"State validity modes"),(0,r.kt)("h3",{id:"pessimistic-full-nodes-only"},"Pessimistic (full nodes only)"),(0,r.kt)("p",null,"A pessimistic rollup is a rollup that only supports full nodes that replay all the transactions in the rollup in order to check its validity. Rollkit supports pessimistic rollups by default."),(0,r.kt)("p",null,"Pessimistic rollups are similar to how Tether uses Bitcoin as a data availability layer via ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/OmniLayer/spec/blob/master/OmniSpecification-v0.6.adoc#summary"},"OmniLayer"),"."),(0,r.kt)("h3",{id:"optimistic-fraud-proofs-work-in-progress"},"Optimistic (fraud proofs) (work in progress)"),(0,r.kt)("p",null,"Rollkit's current design consists of a single sequencer that posts blocks to the DA layer, and multiple (optional) full nodes. Sequencers gossip block headers to full nodes and full nodes fetch posted blocks from the DA layer. Full nodes then execute transactions in these blocks to update their state, and gossip block headers over the P2P network to Rollkit light nodes."),(0,r.kt)("p",null,"Once state fraud proofs are enabled, when a block contains a fraudulent state transition, Rollkit full nodes can detect it by comparing intermediate state roots (ISRs) between transactions, and generate a state fraud proof that can be gossiped over the P2P network to Rollkit light nodes. These Rollkit light nodes can then use this state fraud proof to verify whether a fraudulent state transition occurred or not by themselves."),(0,r.kt)("p",null,"Overall, state fraud proofs will enable trust-minimization between full nodes and light nodes as long as there is at least one honest full node in the system that will generate state fraud proofs."),(0,r.kt)("p",null,"Note that Rollkit state fraud proofs are still a work in progress and will require new methods on top of ABCI, specifically, ",(0,r.kt)("inlineCode",{parentName:"p"},"GenerateFraudProof"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"VerifyFraudProof"),", and ",(0,r.kt)("inlineCode",{parentName:"p"},"GetAppHash"),"."),(0,r.kt)("p",null,"You can find current detailed design and the remaining work needed to push state fraud proofs towards completion in this ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/blob/manav/state_fraud_proofs_adr/docs/lazy-adr/adr-009-state-fraud-proofs.md"},"Architecture Decision Record (ADR)"),"."),(0,r.kt)("h3",{id:"validity-zk-proofs"},"Validity (ZK proofs)"),(0,r.kt)("p",null,"Validity (ZK) rollups are planned, but not currently supported by Rollkit."))}d.isMDXComponent=!0},3334:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/rollkit-abci-75320e3e62c47f3eeebc5b90dd5d01d0.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/c7d6d209.c1f645dd.js b/pr-preview/pr-192/assets/js/c7d6d209.c1f645dd.js deleted file mode 100644 index d5303389d..000000000 --- a/pr-preview/pr-192/assets/js/c7d6d209.c1f645dd.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8696],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,o,r=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o<a.length;o++)n=a[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=o.createContext({}),d=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=d(e.components);return o.createElement(l.Provider,{value:t},e.children)},c="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),c=d(n),p=r,m=c["".concat(l,".").concat(p)]||c[p]||h[p]||a;return n?o.createElement(m,i(i({ref:t},u),{},{components:n})):o.createElement(m,i({ref:t},u))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=p;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[c]="string"==typeof e?e:r,i[1]=s;for(var d=2;d<a;d++)i[d]=n[d];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}p.displayName="MDXCreateElement"},449:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var o=n(7462),r=(n(7294),n(3905));const a={sidebar_label:"Wordle tutorial",description:"Get started with Ignite CLI, Celestia and Rollkit"},i="\ud83d\udd79\ufe0f Wordle app",s={unversionedId:"tutorials/wordle",id:"tutorials/wordle",title:"\ud83d\udd79\ufe0f Wordle app",description:"Get started with Ignite CLI, Celestia and Rollkit",source:"@site/docs/tutorials/wordle.md",sourceDirName:"tutorials",slug:"/tutorials/wordle",permalink:"/pr-preview/pr-192/docs/tutorials/wordle",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/wordle.md",tags:[],version:"current",frontMatter:{sidebar_label:"Wordle tutorial",description:"Get started with Ignite CLI, Celestia and Rollkit"},sidebar:"docs",previous:{title:"Intermediate",permalink:"/pr-preview/pr-192/docs/category/intermediate"},next:{title:"CosmWasm tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/cosmwasm"}},l={},d=[{value:"\ud83d\udcbb Pre-requisites",id:"-pre-requisites",level:2},{value:"\ud83d\udcd6 Design implementation",id:"-design-implementation",level:2},{value:"\ud83d\udccb Table of contents for this tutorial",id:"-table-of-contents-for-this-tutorial",level:2},{value:"\u26d3\ufe0f Ignite and scaffolding the wordle chain",id:"\ufe0f-ignite-and-scaffolding-the-wordle-chain",level:2},{value:"\ud83d\udd25 Ignite",id:"-ignite",level:3},{value:"\u26d3\ufe0f Scaffolding the wordle chain",id:"\ufe0f-scaffolding-the-wordle-chain",level:3},{value:"\ud83d\uddc2\ufe0f Wordle directory",id:"\ufe0f-wordle-directory",level:3},{value:"\ud83d\udee0\ufe0f Setting up Rollkit",id:"\ufe0f-setting-up-rollkit",level:2},{value:"\ud83d\uddde\ufe0f Installing Rollkit",id:"\ufe0f-installing-rollkit",level:3},{value:"\u2728 Creating the wordle module",id:"-creating-the-wordle-module",level:2},{value:"\ud83d\udd16 Scaffolding a module",id:"-scaffolding-a-module",level:3},{value:"\u2709\ufe0f Messages",id:"\ufe0f-messages",level:2},{value:"\ud83d\udcac Scaffolding a message",id:"-scaffolding-a-message",level:3},{value:"\ud83c\udfa8 Wordle types",id:"-wordle-types",level:2},{value:"\ud83c\udfd7\ufe0f Scaffolding wordle types",id:"\ufe0f-scaffolding-wordle-types",level:3},{value:"\ud83d\udd10 Keeper functions",id:"-keeper-functions",level:2},{value:"\ud83d\udce4 <code>SubmitWordle</code> function",id:"-submitwordle-function",level:3},{value:"\u231b <code>SubmitGuess</code> function",id:"-submitguess-function",level:3},{value:"\ud83d\udce6 Protobuf file",id:"-protobuf-file",level:3},{value:"\u26d3\ufe0f Run the wordle chain",id:"\ufe0f-run-the-wordle-chain",level:2},{value:"\ud83e\udeb6 Run a Celestia light node",id:"-run-a-celestia-light-node",level:3},{value:"\ud83d\udfe2 Building and running wordle chain",id:"-building-and-running-wordle-chain",level:3},{value:"\ud83d\udd2e Extending in the future",id:"-extending-in-the-future",level:3}],u={toc:d};function c(e){let{components:t,...a}=e;return(0,r.kt)("wrapper",(0,o.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"\ufe0f-wordle-app"},"\ud83d\udd79\ufe0f Wordle app"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"wordle-app",src:n(3500).Z,width:"2364",height:"1624"})),(0,r.kt)("p",null,"This tutorial guide will go over building a cosmos-sdk app\nfor Rollkit, the Sovereign-Rollup implementation of\nTendermint, for the popular game ",(0,r.kt)("a",{parentName:"p",href:"https://www.nytimes.com/games/wordle/index.html"},"Wordle"),"."),(0,r.kt)("p",null,"This tutorial will go over how to setup Rollkit\nin the Ignite CLI and use it to build the game.\nThe tutorial will go over the simple design,\nas well as conclude with future implementations and ideas\nto extend this codebase."),(0,r.kt)("admonition",{title:"note",type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"This tutorial will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"Issue ticket"),"\nor let us know in our ",(0,r.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),".")),(0,r.kt)("admonition",{title:"caution",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"The script for this tutorial is built for Celestia's\n",(0,r.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspacerace testnet"),".\nIf you choose to use Mocha testnet or Arabica devnet,\nyou will need to modify the script manually.")),(0,r.kt)("h2",{id:"-pre-requisites"},"\ud83d\udcbb Pre-requisites"),(0,r.kt)("p",null,"Given this tutorial is targeted for developers who are experienced\nin Cosmos-SDK, we recommend you go over the following tutorials\nin Ignite to understand all the different components in Cosmos-SDK before\nproceeding with this tutorial."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/gm-world"},"GM World")," or ",(0,r.kt)("a",{parentName:"li",href:"https://docs.ignite.com/guide/hello/scaffolding"},"Hello, World")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/recipe-book"},"Recipe Book")," or ",(0,r.kt)("a",{parentName:"li",href:"https://docs.ignite.com/guide/blog/intro"},"Blog and Module Basics")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.ignite.com/v0.25.2/guide/nameservice"},"Nameservice Tutorial")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.ignite.com/v0.25.2/guide/scavenge"},"Scavenger Hunt"))),(0,r.kt)("p",null,"You do not have to do those guides in order to follow this Wordle tutorial,\nbut doing so helps you understand the architecture of Cosmos-SDK better."),(0,r.kt)("h2",{id:"-design-implementation"},"\ud83d\udcd6 Design implementation"),(0,r.kt)("p",null,"The rules of Wordle are simple: You have to guess the word of the day."),(0,r.kt)("p",null,"Key Points to Consider:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The word is a five-letter word."),(0,r.kt)("li",{parentName:"ul"},"You have 6 guesses."),(0,r.kt)("li",{parentName:"ul"},"Every 24 hours, there\u2019s a new word.")),(0,r.kt)("p",null,"The GUI for Wordle shows you a few indicators: a\ngreen highlight on a letter in a certain position\nmeans that\u2019s the correct letter for the Wordle\nin the right position. A yellow highlight means\nit\u2019s a correct letter for the Wordle included in\nthe wrong position. A grey highlight means the letter\nisn\u2019t part of the Wordle."),(0,r.kt)("p",null,"For simplicity of the design, we will avoid those\nhints, although there are ways to extend this codebase\nto implement that, which we will show at the end."),(0,r.kt)("p",null,"In this current design, we implement the following rules:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"1 Wordle can be submitted per day"),(0,r.kt)("li",{parentName:"ul"},"Every address will have 6 tries to guess the word"),(0,r.kt)("li",{parentName:"ul"},"It must be a five-letter word. "),(0,r.kt)("li",{parentName:"ul"},"Whoever guesses the word correctly before their\n6 tries are over gets an award of 100 WORDLE tokens.")),(0,r.kt)("p",null,"We will go over the architecture to achieve this further\nin the guide. But for now, we will get started setting up\nour development environment."),(0,r.kt)("h2",{id:"-table-of-contents-for-this-tutorial"},"\ud83d\udccb Table of contents for this tutorial"),(0,r.kt)("p",null,"The following tutorial is broken down into the following\nsections:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#ignite-and-scaffolding-the-wordle-chain"},"Ignite and Chain Scaffolding")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#setting-up-rollkit"},"Installing Rollkit")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#creating-the-wordle-module"},"Modules")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#messages"},"Messages")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#wordle-types"},"Types")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#keeper-functions"},"Keepers")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"#run-the-wordle-chain"},"Running Wordle"))),(0,r.kt)("h2",{id:"\ufe0f-ignite-and-scaffolding-the-wordle-chain"},"\u26d3\ufe0f Ignite and scaffolding the wordle chain"),(0,r.kt)("h3",{id:"-ignite"},"\ud83d\udd25 Ignite"),(0,r.kt)("p",null,"Ignite is an amazing CLI tool to help us get started building\nour own blockchains for cosmos-sdk apps. It provides lots of\npower toolings and scaffoldings for adding messages, types,\nand modules with a host of cosmos-sdk libraries provided."),(0,r.kt)("p",null,"You can read more about Ignite ",(0,r.kt)("a",{parentName:"p",href:"https://docs.ignite.com"},"here"),"."),(0,r.kt)("p",null,"To install Ignite, you can run this command in your terminal:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"curl https://get.ignite.com/cli@v0.26.1! | bash\nsudo mv ignite /usr/local/bin/\n")),(0,r.kt)("p",null,"This installs Ignite CLI in your local machine.\nThis tutorial uses a MacOS but it should work for Windows.\nFor Windows users, check out the Ignite docs on installation\nfor Windows machines."),(0,r.kt)("p",null,"Now, refresh your terminal using ",(0,r.kt)("inlineCode",{parentName:"p"},"source")," or open a new terminal\nsession for the change to take place."),(0,r.kt)("p",null,"If you run the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite --help\n")),(0,r.kt)("p",null,"You should see an output of help commands meaning Ignite\nwas installed successfully!"),(0,r.kt)("h3",{id:"\ufe0f-scaffolding-the-wordle-chain"},"\u26d3\ufe0f Scaffolding the wordle chain"),(0,r.kt)("p",null,"Now, comes the fun part, creating a new blockchain! With Ignite,\nthe process is pretty easy and straightforward."),(0,r.kt)("p",null,"Ignite CLI comes with several scaffolding commands that are\ndesigned to make development more straightforward by creating\neverything you need to build your blockchain."),(0,r.kt)("p",null,"First, we will use Ignite CLI to build the foundation of a fresh\nCosmos SDK blockchain. Ignite minimizes how much blockchain code\nyou must write yourself. If you are coming from the EVM-world, think of\nIgnite as a Cosmos-SDK version of Foundry or Hardhat but specifically\ndesigned to build blockchains."),(0,r.kt)("p",null,"We first run the following command to setup our project for\nour new blockchain, Wordle."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold chain wordle --no-module\n")),(0,r.kt)("p",null,"This command scaffolds a new chain directory called ",(0,r.kt)("inlineCode",{parentName:"p"},"wordle"),"\nin your local directory from which you ran the command. Notice\nthat we passed the ",(0,r.kt)("inlineCode",{parentName:"p"},"--no-module")," flag, this is because we will be\ncreating the module after."),(0,r.kt)("h3",{id:"\ufe0f-wordle-directory"},"\ud83d\uddc2\ufe0f Wordle directory"),(0,r.kt)("p",null,"Now, it\u2019s time to enter the directory:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"cd wordle\n")),(0,r.kt)("p",null,"Inside you will see several directories and architecture for\nyour cosmos-sdk blockchain."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"File/directory"),(0,r.kt)("th",{parentName:"tr",align:null},"Purpose"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"app/"),(0,r.kt)("td",{parentName:"tr",align:null},"Files that wire together the blockchain. The most important file is ",(0,r.kt)("inlineCode",{parentName:"td"},"app.go")," that contains type definition of the blockchain and functions to create and initialize it.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"cmd/"),(0,r.kt)("td",{parentName:"tr",align:null},"The main package responsible for the CLI of compiled binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"docs/"),(0,r.kt)("td",{parentName:"tr",align:null},"Directory for project documentation. By default, an OpenAPI spec is generated.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"proto/"),(0,r.kt)("td",{parentName:"tr",align:null},"Protocol buffer files describing the data structure.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"testutil/"),(0,r.kt)("td",{parentName:"tr",align:null},"Helper functions for testing.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"vue/"),(0,r.kt)("td",{parentName:"tr",align:null},"A Vue 3 web app template.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"x/"),(0,r.kt)("td",{parentName:"tr",align:null},"Cosmos SDK modules and custom modules.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"config.yml"),(0,r.kt)("td",{parentName:"tr",align:null},"A configuration file for customizing a chain in development.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"readme.md"),(0,r.kt)("td",{parentName:"tr",align:null},"A readme file for your sovereign application-specific blockchain project.")))),(0,r.kt)("p",null,"Going over each one is outside the scope of this guide, but we encourage you\nto read about it ",(0,r.kt)("a",{parentName:"p",href:"https://docs.ignite.com/v0.25.2/kb"},"here"),"."),(0,r.kt)("p",null,"Most of the tutorial work will happen inside the ",(0,r.kt)("inlineCode",{parentName:"p"},"x")," directory."),(0,r.kt)("h2",{id:"\ufe0f-setting-up-rollkit"},"\ud83d\udee0\ufe0f Setting up Rollkit"),(0,r.kt)("p",null,"Before we continue with building our Wordle App, we need to set up\nRollkit on our codebase."),(0,r.kt)("h3",{id:"\ufe0f-installing-rollkit"},"\ud83d\uddde\ufe0f Installing Rollkit"),(0,r.kt)("p",null,"Run the following command inside the ",(0,r.kt)("inlineCode",{parentName:"p"},"wordle")," directory."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs\ngo mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d\ngo mod tidy\ngo mod download\n")),(0,r.kt)("p",null,"With that, we have Rollkit changes added to the project directory. Now,\nlet's build the Wordle app!"),(0,r.kt)("h2",{id:"-creating-the-wordle-module"},"\u2728 Creating the wordle module"),(0,r.kt)("p",null,"For the Wordle module, we can add dependencies offered by Cosmos-SDK."),(0,r.kt)("p",null,"From the Cosmos-SDK docs, a ",(0,r.kt)("a",{parentName:"p",href:"https://docs.ignite.com/v0.25.2/guide/nameservice#cosmos-sdk-modules"},"module"),"\nis defined as the following:"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"In a Cosmos SDK blockchain, application-specific logic\nis implemented in separate modules. Modules keep code easy\nto understand and reuse. Each module contains its own message\nand transaction processor, while the Cosmos SDK is responsible\nfor routing each message to its respective module.")),(0,r.kt)("p",null,"Many modules exist for slashing, validating, auth."),(0,r.kt)("h3",{id:"-scaffolding-a-module"},"\ud83d\udd16 Scaffolding a module"),(0,r.kt)("p",null,"We will be using the ",(0,r.kt)("inlineCode",{parentName:"p"},"bank")," module dependency for transactions."),(0,r.kt)("p",null,"From the Cosmos-SDK docs, the ",(0,r.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main/modules/bank"},(0,r.kt)("inlineCode",{parentName:"a"},"bank")),"\nmodule is defined as the following:"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"The bank module is responsible for handling multi-asset coin\ntransfers between accounts and tracking special-case pseudo-transfers\nwhich must work differently with particular kinds of accounts\n(notably delegating/undelegating for vesting accounts). It exposes\nseveral interfaces with varying capabilities for secure interaction\nwith other modules which must alter user balances.")),(0,r.kt)("p",null,"We build the module with the ",(0,r.kt)("inlineCode",{parentName:"p"},"bank")," dependency with the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold module wordle --dep bank\n")),(0,r.kt)("p",null,"This will scaffold the Wordle module to our Wordle Chain project."),(0,r.kt)("h2",{id:"\ufe0f-messages"},"\u2709\ufe0f Messages"),(0,r.kt)("p",null,"Messages allow us to process and submit information to our specific module."),(0,r.kt)("p",null,"From the Cosmos-SDK docs, ",(0,r.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main/building-modules/messages-and-queries.html#messages"},"messages"),"\nare:"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"In the Cosmos SDK, messages are objects that are contained\nin transactions to trigger state transitions. Each Cosmos SDK\nmodule defines a list of messages and how to handle them.")),(0,r.kt)("p",null,"For messages for Wordle, given our initial design, we will\nmake 2 messages with ignite."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The first one is: ",(0,r.kt)("inlineCode",{parentName:"li"},"SubmitWordle")," and it only passes the Wordle of the Day."),(0,r.kt)("li",{parentName:"ul"},"The second one is: ",(0,r.kt)("inlineCode",{parentName:"li"},"SubmitGuess")," and it attempts to guess the submitted\nwordle. It also passes a word as a guess.")),(0,r.kt)("p",null,"With these initial designs, we can start creating our messages!"),(0,r.kt)("h3",{id:"-scaffolding-a-message"},"\ud83d\udcac Scaffolding a message"),(0,r.kt)("p",null,"To create the ",(0,r.kt)("inlineCode",{parentName:"p"},"SubmitWordle")," message, we run the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold message submit-wordle word\n")),(0,r.kt)("p",null,"This creates the ",(0,r.kt)("inlineCode",{parentName:"p"},"submit-wordle")," message that takes in ",(0,r.kt)("inlineCode",{parentName:"p"},"word")," as a parameter."),(0,r.kt)("p",null,"We now create the final message, ",(0,r.kt)("inlineCode",{parentName:"p"},"SubmitGuess"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold message submit-guess word\n")),(0,r.kt)("p",null,"Here, we are passing a word as a guess with ",(0,r.kt)("inlineCode",{parentName:"p"},"submit-guess"),"."),(0,r.kt)("h2",{id:"-wordle-types"},"\ud83c\udfa8 Wordle types"),(0,r.kt)("p",null,"For the next steps, we will be creating types to be used by\nthe messages we created."),(0,r.kt)("h3",{id:"\ufe0f-scaffolding-wordle-types"},"\ud83c\udfd7\ufe0f Scaffolding wordle types"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold map wordle word submitter --no-message\n")),(0,r.kt)("p",null,"This type is a map called ",(0,r.kt)("inlineCode",{parentName:"p"},"Wordle")," with two values of\n",(0,r.kt)("inlineCode",{parentName:"p"},"word")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"submitter"),". ",(0,r.kt)("inlineCode",{parentName:"p"},"submitter")," is the address of the\nperson that submitted the Wordle."),(0,r.kt)("p",null,"The second type is the ",(0,r.kt)("inlineCode",{parentName:"p"},"Guess")," type. It allows us to store\nthe latest guess for each address that submitted a solution."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"ignite scaffold map guess word submitter count --no-message\n")),(0,r.kt)("p",null,"Here, we are also storing ",(0,r.kt)("inlineCode",{parentName:"p"},"count")," to count how many guesses\nthis address submitted."),(0,r.kt)("h2",{id:"-keeper-functions"},"\ud83d\udd10 Keeper functions"),(0,r.kt)("p",null,"Now it\u2019s time to implement the Keeper functions for each\nmessage. From the Cosmos-SDK docs, ",(0,r.kt)("a",{parentName:"p",href:"https://docs.cosmos.network/main/building-modules/keeper.html"},"Keeper"),"\nis defined as the following:"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"The main core of a Cosmos SDK module is a piece called the keeper.\nThe keeper handles interactions with the store, has references\nto other keepers for cross-module interactions, and contains most\nof the core functionality of a module.")),(0,r.kt)("p",null,"Keeper is an abstraction on Cosmos that allows us\nto interact with the Key-Value store and change the state\nof the blockchain."),(0,r.kt)("p",null,"Here, it will help us outline the logic for each message we create."),(0,r.kt)("h3",{id:"-submitwordle-function"},"\ud83d\udce4 ",(0,r.kt)("inlineCode",{parentName:"h3"},"SubmitWordle")," function"),(0,r.kt)("p",null,"We first start with the ",(0,r.kt)("inlineCode",{parentName:"p"},"SubmitWordle")," function."),(0,r.kt)("p",null,"Open up the following file: ",(0,r.kt)("inlineCode",{parentName:"p"},"x/wordle/keeper/msg_server_submit_wordle.go")),(0,r.kt)("p",null,"Inside the following, replace the current code with the following code,\nwhich we will go over in a bit:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="x/wordle/keeper/msg_server_submit_wordle.go"',title:'"x/wordle/keeper/msg_server_submit_wordle.go"'},'package keeper\n\nimport (\n "context"\n "crypto/sha256"\n "encoding/hex"\n "wordle/x/wordle/types"\n sdk "github.com/cosmos/cosmos-sdk/types"\n sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"\n "time"\n "unicode"\n "github.com/tendermint/tendermint/crypto"\n)\n\nfunc (k msgServer) SubmitWordle(goCtx context.Context, msg *types.MsgSubmitWordle) (*types.MsgSubmitWordleResponse, error) {\n ctx := sdk.UnwrapSDKContext(goCtx)\n // Check to See the Wordle is 5 letters\n if len(msg.Word) != 5 {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle Must Be A 5 Letter Word")\n }\n // Check to See Only Alphabets Are Passed for the Wordle\n if !(IsLetter(msg.Word)) {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle Must Only Consist Of Letters In The Alphabet")\n }\n\n // Use Current Day to Create The Index of the Newly-Submitted Wordle of the Day\n currentTime := time.Now().Local()\n var currentTimeBytes = []byte(currentTime.Format("2006-01-02"))\n var currentTimeHash = sha256.Sum256(currentTimeBytes)\n var currentTimeHashString = hex.EncodeToString(currentTimeHash[:])\n // Hash The Newly-Submitted Wordle of the Day\n var submittedSolutionHash = sha256.Sum256([]byte(msg.Word))\n var submittedSolutionHashString = hex.EncodeToString(submittedSolutionHash[:])\n\n var wordle = types.Wordle{\n Index: currentTimeHashString,\n Word: submittedSolutionHashString,\n Submitter: msg.Creator,\n }\n\n // Try to Get Wordle From KV Store Using Current Day as Key\n // This Helps ensure only one Wordle is submitted per day\n _, isFound := k.GetWordle(ctx, currentTimeHashString)\n if isFound {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle of the Day is Already Submitted")\n }\n // Write Wordle to KV Store\n k.SetWordle(ctx, wordle)\n reward := sdk.Coins{sdk.NewInt64Coin("token", 100)}\n // Escrow Reward\n submitterAddress, _ := sdk.AccAddressFromBech32(msg.Creator)\n moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName)))\n err := k.bankKeeper.SendCoins(ctx, submitterAddress, moduleAcct, reward)\n if err != nil {\n return nil, err\n }\n return &types.MsgSubmitWordleResponse{}, nil\n}\n\nfunc IsLetter(s string) bool {\n for _, r := range s {\n if !unicode.IsLetter(r) {\n return false\n }\n }\n return true\n}\n')),(0,r.kt)("p",null,"Here in the ",(0,r.kt)("inlineCode",{parentName:"p"},"SubmitWordle")," Keeper function, we are doing a few things:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"We first ensure that a word submitted for Wordle of the Day is\n5 letters long and only uses alphabets. That means no integers can\nbe submitted in the string."),(0,r.kt)("li",{parentName:"ul"},"We then create a hash from the current day the moment the Wordle was\nsubmitted. We set this hash to the index of the Wordle type. This\nallows us to look up any guesses for this Wordle for subsequent\nguesses, which we will go over next."),(0,r.kt)("li",{parentName:"ul"},"We then check if the index for today\u2019s date is currently empty or\nnot. If it\u2019s not empty, this means a Wordle has already been\nsubmitted. Remember, only one wordle can be submitted per\nday. Everyone else has to guess the submitted wordle."),(0,r.kt)("li",{parentName:"ul"},"We also have a helper function in there to check if a string only\ncontains alphabet characters.")),(0,r.kt)("h3",{id:"-submitguess-function"},"\u231b ",(0,r.kt)("inlineCode",{parentName:"h3"},"SubmitGuess")," function"),(0,r.kt)("p",null,"The next Keeper function we will add is the following:\n",(0,r.kt)("inlineCode",{parentName:"p"},"x/wordle/keeper/msg_server_submit_guess.go")),(0,r.kt)("p",null,"Open that file and replace its contents with the following code, which we will\nexplain in a bit:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="x/wordle/keeper/msg_server_submit_guess.go"',title:'"x/wordle/keeper/msg_server_submit_guess.go"'},'package keeper\n\nimport (\n "context"\n "crypto/sha256"\n "encoding/hex"\n "wordle/x/wordle/types"\n sdk "github.com/cosmos/cosmos-sdk/types"\n sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"\n "strconv"\n "time"\n "github.com/tendermint/tendermint/crypto"\n)\n\nfunc (k msgServer) SubmitGuess(goCtx context.Context, msg *types.MsgSubmitGuess) (*types.MsgSubmitGuessResponse, error) {\n ctx := sdk.UnwrapSDKContext(goCtx)\n // Check Word is 5 Characters Long\n if len(msg.Word) != 5 {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Guess Must Be A 5 Letter Word!")\n }\n \n // Check String Contains Alphabet Letters Only\n if !(IsLetter(msg.Word)) {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Guess Must Only Consist of Alphabet Letters!")\n }\n\n // Get Current Day to Pull Up Wordle of That Day As A Hash\n currentTime := time.Now().Local()\n var currentTimeBytes = []byte(currentTime.Format("2006-01-02"))\n var currentTimeHash = sha256.Sum256(currentTimeBytes)\n var currentTimeHashString = hex.EncodeToString(currentTimeHash[:])\n wordle, isFound := k.GetWordle(ctx, currentTimeHashString)\n if !isFound {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle of The Day Hasn\'t Been Submitted Yet. Feel Free to Submit One!")\n }\n\n // We Convert Current Day and Guesser to A Hash To Use As An Index For Today\'s Guesses For That Guesser\n // That Way, A Person Can Guess 6 Times A Day For Each New Wordle Created\n var currentTimeGuesserBytes = []byte(currentTime.Format("2006-01-02") + msg.Creator)\n var currentTimeGuesserHash = sha256.Sum256(currentTimeGuesserBytes)\n var currentTimeGuesserHashString = hex.EncodeToString(currentTimeGuesserHash[:])\n // Hash The Guess To The Wordle\n var submittedSolutionHash = sha256.Sum256([]byte(msg.Word))\n var submittedSolutionHashString = hex.EncodeToString(submittedSolutionHash[:])\n\n // Get the Latest Guess entry for this Submitter for the current Wordle of the Day\n var count int\n guess, isFound := k.GetGuess(ctx, currentTimeGuesserHashString)\n if isFound {\n // Check if Submitter Reached 6 Tries\n if guess.Count == strconv.Itoa(6) {\n return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "You Have Guessed The Maximum Amount of Times for The Day! Try Again Tomorrow With A New Wordle.")\n }\n currentCount, err := strconv.Atoi(guess.Count)\n if err != nil {\n panic(err)\n }\n count = currentCount\n } else {\n // Initialize Count Value If No Entry Exists for this Submitter for Today\'s Wordle\n count = 0\n }\n // Increment Guess Count\n count += 1\n var newGuess = types.Guess{\n Index: currentTimeGuesserHashString,\n Submitter: msg.Creator,\n Word: submittedSolutionHashString,\n Count: strconv.Itoa(count),\n }\n // Remove Current Guess Entry to be Updated With New Entry\n k.RemoveGuess(ctx, currentTimeGuesserHashString)\n // Add New Guess Entry\n k.SetGuess(ctx, newGuess)\n if !(wordle.Word == submittedSolutionHashString) {\n return &types.MsgSubmitGuessResponse{Title: "Wrong Answer", Body: "Your Guess Was Wrong. Try Again"}, nil\n } else {\n // Setup Reward \n reward := sdk.Coins{sdk.NewInt64Coin("token", 100)}\n // If Submitter Guesses Correctly\n guesserAddress, _ := sdk.AccAddressFromBech32(msg.Creator)\n moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName)))\n // Send Reward\n err := k.bankKeeper.SendCoins(ctx, moduleAcct, guesserAddress, reward)\n if err !=nil {\n return nil, err\n }\n return &types.MsgSubmitGuessResponse{Title: "Correct", Body: "You Guessed The Wordle Correctly!"}, nil\n }\n}\n')),(0,r.kt)("p",null,"In the above code, we are doing the following things:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Here, we are doing initial checks again on the word to ensure\nit\u2019s 5 characters and only alphabet characters are used, which\ncan be refactored in the future or checked within the CLI commands."),(0,r.kt)("li",{parentName:"ul"},"We then get the Wordle of the Day by getting the hash string of\nthe current day."),(0,r.kt)("li",{parentName:"ul"},"Next we create a hash string of current day and the Submitter.\nThis allows us to create a Guess type with an index that uses the\ncurrent day and the address of the submitter. This helps us when we\nface a new day and an address wants to guess the new wordle of the day.\nThe index setup ensures they can continue guessing a new wordle\nevery day up to the max of 6 tries per day."),(0,r.kt)("li",{parentName:"ul"},"We then check if that Guess type for the Submitter for today\u2019s\nwordle did reach 6 counts. If it hasn\u2019t, we increment the count.\nWe then check if the guess is correct. We store the Guess type with\nthe updated count to the state.")),(0,r.kt)("h3",{id:"-protobuf-file"},"\ud83d\udce6 Protobuf file"),(0,r.kt)("p",null," A few files need to be modified for this to work."),(0,r.kt)("p",null,"The first is ",(0,r.kt)("inlineCode",{parentName:"p"},"proto/wordle/wordle/tx.proto"),"."),(0,r.kt)("p",null,"Inside this file, fill in the empty ",(0,r.kt)("inlineCode",{parentName:"p"},"MsgSubmitGuessResponse"),"\nwith the following code:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="proto/wordle/tx.proto"',title:'"proto/wordle/tx.proto"'},"message MsgSubmitGuessResponse {\n string title = 1;\n string body = 2;\n}\n")),(0,r.kt)("p",null,"Next file is ",(0,r.kt)("inlineCode",{parentName:"p"},"x/wordle/types/expected_keepers.go")),(0,r.kt)("p",null,"Here, we need to add the SendCoins method to the BankKeeper\ninterface in order to allow sending the reward to the right guesser."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="x/wordle/types/expected_keepers.go"',title:'"x/wordle/types/expected_keepers.go"'},"type BankKeeper interface {\n SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error\n}\n")),(0,r.kt)("p",null,"With that, we implemented all our Keeper functions! Time to\ncompile the blockchain and take it out for a test drive."),(0,r.kt)("h2",{id:"\ufe0f-run-the-wordle-chain"},"\u26d3\ufe0f Run the wordle chain"),(0,r.kt)("h3",{id:"-run-a-celestia-light-node"},"\ud83e\udeb6 Run a Celestia light node"),(0,r.kt)("p",null,"Follow instructions to install and start your Celestia Data\nAvailalbility layer Light Node selecting the network that\nyou had previously used. You can find instructions to install\nand run the node ",(0,r.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/light-node"},"here"),"."),(0,r.kt)("p",null,"After you have Go and Ignite CLI installed, and your Celestia\nLight Node running on your machine, you're ready to build,\ntest, and launch your own sovereign rollup."),(0,r.kt)("h3",{id:"-building-and-running-wordle-chain"},"\ud83d\udfe2 Building and running wordle chain"),(0,r.kt)("p",null,"We have a handy ",(0,r.kt)("inlineCode",{parentName:"p"},"init.sh")," found in this repo\n",(0,r.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/tree/main/docs/scripts/wordle"},"here"),"."),(0,r.kt)("p",null,"We can copy it over to our directory with the following commands:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# From inside the `wordle` directory\nwget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/wordle/init.sh\n")),(0,r.kt)("p",null,"This copies over our ",(0,r.kt)("inlineCode",{parentName:"p"},"init.sh")," script to initialize our\nWordle Rollup."),(0,r.kt)("p",null,"You can view the contents of the script to see how we\ninitialize the Wordle Rollup."),(0,r.kt)("admonition",{title:"caution",type:"danger"},(0,r.kt)("p",{parentName:"admonition"},"On some machines, before starting our rollup, we'll need to find\nand change ",(0,r.kt)("inlineCode",{parentName:"p"},"FlagIAVLFastNode")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"FlagDisableIAVLFastNode"),":"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-go",metastring:'title="wordle/cmd/wordled/cmd/root.go"',title:'"wordle/cmd/wordled/cmd/root.go"'},"baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(server.FlagDisableIAVLFastNode))),\n"))),(0,r.kt)("p",null,"You can initialize the script with the following command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"bash init.sh\n")),(0,r.kt)("p",null,"With that, we have kickstarted our ",(0,r.kt)("inlineCode",{parentName:"p"},"wordled")," network!"),(0,r.kt)("p",null,"In another window, run the following to submit a Wordle:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled tx wordle submit-wordle giant --from wordle-key --keyring-backend test --chain-id wordle -b async -y\n")),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"NOTE: We are submitting a transaction asynchronously due to avoiding\nany timeout errors. With Rollkit as a replacement to Tendermint, we\nneed to wait for Celestia's Data-Availability network to ensure a block\nwas included from Wordle, before proceeding to the next block. Currently,\nin Rollkit, the single aggregator is not moving forward with the next block\nproduction as long as it is trying to submit the current block to the DA network.\nIn the future, with leader selection, block production and sync logic improves\ndramatically.")),(0,r.kt)("p",null,"This will ask you to confirm the transaction with the following message:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'{\n "body":{\n "messages":[\n {\n "@type":"/YazzyYaz.wordle.wordle.MsgSubmitWordle",\n "creator":"cosmos17lk3fgutf00pd5s8zwz5fmefjsdv4wvzyg7d74",\n "word":"giant"\n }\n ],\n "memo":"",\n "timeout_height":"0",\n "extension_options":[\n ],\n "non_critical_extension_options":[\n ]\n },\n "auth_info":{\n "signer_infos":[\n ],\n "fee":{\n "amount":[\n ],\n "gas_limit":"200000",\n "payer":"",\n "granter":""\n }\n },\n "signatures":[\n ]\n}\n')),(0,r.kt)("p",null,"Cosmos-SDK will ask you to confirm the transaction here:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"confirm transaction before signing and broadcasting [y/N]:\n")),(0,r.kt)("p",null,"Confirm with a Y."),(0,r.kt)("p",null,"You will then get a response with a transaction hash as shown here:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},'code: 0\ncodespace: ""\ndata: ""\nevents: []\ngas_used: "0"\ngas_wanted: "0"\nheight: "0"\ninfo: ""\nlogs: []\nraw_log: ""\ntimestamp: ""\ntx: null\ntxhash: F159E11116EC9505FC2C0D97E605357FEC0F3DAE06B57BFB17EA6A548905043E\n')),(0,r.kt)("p",null,"Note, this does not mean the transaction was included in the block yet.\nLet's query the transaction hash to check whether it has been included in\nthe block yet or if there are any errors."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled query tx --type=hash F159E11116EC9505FC2C0D97E605357FEC0F3DAE06B57BFB17EA6A548905043E --chain-id wordle --output json | jq -r '.raw_log'\n")),(0,r.kt)("p",null,"This should display an output like the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-json"},'[{"events":[{"type":"message","attributes":[{"key":"action","value":"submit_wordle"\n}]}]}]\n')),(0,r.kt)("p",null,"Test out a few things for fun:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled tx wordle submit-guess 12345 --from wordle-key --keyring-backend test --chain-id wordle -b async -y\n")),(0,r.kt)("p",null,"After confirming the transaction, query the ",(0,r.kt)("inlineCode",{parentName:"p"},"txhash"),"\ngiven the same way you did above. You will see the response shows\nan Invalid Error because you submitted integers."),(0,r.kt)("p",null,"Now try:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled tx wordle submit-guess ABCDEFG --from wordle-key --keyring-backend test --chain-id wordle -b async -y\n")),(0,r.kt)("p",null,"After confirming the transaction, query the ",(0,r.kt)("inlineCode",{parentName:"p"},"txhash")," given the same\nway you did above. You will see the response shows\nan Invalid Error because you submitted a word larger than 5 characters."),(0,r.kt)("p",null,"Now try to submit another wordle even though one was already submitted"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled tx wordle submit-wordle meter --from wordle-key --keyring-backend test --chain-id wordle -b async -y\n")),(0,r.kt)("p",null,"After submitting the transactions and confirming, query the ",(0,r.kt)("inlineCode",{parentName:"p"},"txhash"),"\ngiven the same way you did above. You will get an error that a wordle\nhas already been submitted for the day."),(0,r.kt)("p",null,"Now let\u2019s try to guess a five letter word:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled tx wordle submit-guess least --from wordle-key --keyring-backend test --chain-id wordle -b async -y\n")),(0,r.kt)("p",null,"After submitting the transactions and confirming, query the ",(0,r.kt)("inlineCode",{parentName:"p"},"txhash"),"\ngiven the same way you did above. Given you didn\u2019t guess the correct\nword, it will increment the guess count for wordle-key's account."),(0,r.kt)("p",null,"We can verify this by querying the list:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"wordled q wordle list-guess --output json\n")),(0,r.kt)("p",null,"This outputs all Guess objects submitted so far, with the index\nbeing today\u2019s date and the address of the submitter."),(0,r.kt)("p",null,"With that, we implemented a basic example of Wordle using\nCosmos-SDK and Ignite and Rollkit. Read on to how you can\nextend the code base."),(0,r.kt)("h3",{id:"-extending-in-the-future"},"\ud83d\udd2e Extending in the future"),(0,r.kt)("p",null,"You can extend the codebase and improve this tutorial by checking\nout the repository ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/celestiaorg/wordle"},"here"),"."),(0,r.kt)("p",null,"There are many ways this codebase can be extended:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"You can improve messaging around when you guess the correct word."),(0,r.kt)("li",{parentName:"ol"},"You can hash the word prior to submitting it to the chain,\nensuring the hashing is local so that it\u2019s not revealed via\nfront-running by others monitoring the plaintext string when\nit\u2019s submitted on-chain."),(0,r.kt)("li",{parentName:"ol"},"You can improve the UI in terminal using a nice interface for\nWordle. Some examples are ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/nimblebun/wordle-cli"},"here"),"."),(0,r.kt)("li",{parentName:"ol"},"You can improve current date to stick to a specific timezone."),(0,r.kt)("li",{parentName:"ol"},"You can create a bot that submits a wordle every day at a specific time."),(0,r.kt)("li",{parentName:"ol"},"You can create a vue.js front-end with Ignite using example open-source\nrepositories ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/yyx990803/vue-wordle"},"here")," and ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/xudafeng/wordle"},"here"),".")))}c.isMDXComponent=!0},3500:(e,t,n)=>{n.d(t,{Z:()=>o});const o=n.p+"assets/images/wordle-cd3a9ac164294b1a4acd7ffa6a63fd7b.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/ccc49370.9164d42e.js b/pr-preview/pr-192/assets/js/ccc49370.9164d42e.js deleted file mode 100644 index 0c410477c..000000000 --- a/pr-preview/pr-192/assets/js/ccc49370.9164d42e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6103],{5203:(e,t,n)=>{n.r(t),n.d(t,{default:()=>h});var a=n(7294),l=n(6010),r=n(1944),o=n(5281),i=n(9460),c=n(9058),s=n(390),m=n(7462),d=n(5999),u=n(2244);function g(e){const{nextItem:t,prevItem:n}=e;return a.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,d.I)({id:"theme.blog.post.paginator.navAriaLabel",message:"Blog post page navigation",description:"The ARIA label for the blog posts pagination"})},n&&a.createElement(u.Z,(0,m.Z)({},n,{subLabel:a.createElement(d.Z,{id:"theme.blog.post.paginator.newerPost",description:"The blog post button label to navigate to the newer/previous post"},"Newer Post")})),t&&a.createElement(u.Z,(0,m.Z)({},t,{subLabel:a.createElement(d.Z,{id:"theme.blog.post.paginator.olderPost",description:"The blog post button label to navigate to the older/next post"},"Older Post"),isNext:!0})))}function f(){const{assets:e,metadata:t}=(0,i.C)(),{title:n,description:l,date:o,tags:c,authors:s,frontMatter:m}=t,{keywords:d}=m,u=e.image??m.image;return a.createElement(r.d,{title:n,description:l,keywords:d,image:u},a.createElement("meta",{property:"og:type",content:"article"}),a.createElement("meta",{property:"article:published_time",content:o}),s.some((e=>e.url))&&a.createElement("meta",{property:"article:author",content:s.map((e=>e.url)).filter(Boolean).join(",")}),c.length>0&&a.createElement("meta",{property:"article:tag",content:c.map((e=>e.label)).join(",")}))}var v=n(9407);function p(e){let{sidebar:t,children:n}=e;const{metadata:l,toc:r}=(0,i.C)(),{nextItem:o,prevItem:m,frontMatter:d}=l,{hide_table_of_contents:u,toc_min_heading_level:f,toc_max_heading_level:p}=d;return a.createElement(c.Z,{sidebar:t,toc:!u&&r.length>0?a.createElement(v.Z,{toc:r,minHeadingLevel:f,maxHeadingLevel:p}):void 0},a.createElement(s.Z,null,n),(o||m)&&a.createElement(g,{nextItem:o,prevItem:m}))}function h(e){const t=e.content;return a.createElement(i.n,{content:e.content,isBlogPostPage:!0},a.createElement(r.FG,{className:(0,l.Z)(o.k.wrapper.blogPages,o.k.page.blogPostPage)},a.createElement(f,null),a.createElement(p,{sidebar:e.sidebar},a.createElement(t,null))))}},9407:(e,t,n)=>{n.d(t,{Z:()=>c});var a=n(7462),l=n(7294),r=n(6010),o=n(3743);const i="tableOfContents_bqdL";function c(e){let{className:t,...n}=e;return l.createElement("div",{className:(0,r.Z)(i,"thin-scrollbar",t)},l.createElement(o.Z,(0,a.Z)({},n,{linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})))}},3743:(e,t,n)=>{n.d(t,{Z:()=>f});var a=n(7462),l=n(7294),r=n(6668);function o(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const a=n.slice(2,e.level);e.parentIndex=Math.max(...a),n[e.level]=t}));const a=[];return t.forEach((e=>{const{parentIndex:n,...l}=e;n>=0?t[n].children.push(l):a.push(l)})),a}function i(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return t.flatMap((e=>{const t=i({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[{...e,children:t}]:t}))}function c(e){const t=e.getBoundingClientRect();return t.top===t.bottom?c(e.parentNode):t}function s(e,t){let{anchorTopOffset:n}=t;const a=e.find((e=>c(e).top>=n));if(a){return function(e){return e.top>0&&e.bottom<window.innerHeight/2}(c(a))?a:e[e.indexOf(a)-1]??null}return e[e.length-1]??null}function m(){const e=(0,l.useRef)(0),{navbar:{hideOnScroll:t}}=(0,r.L)();return(0,l.useEffect)((()=>{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function d(e){const t=(0,l.useRef)(void 0),n=m();(0,l.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:a,linkActiveClassName:l,minHeadingLevel:r,maxHeadingLevel:o}=e;function i(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(a),i=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const a=[];for(let l=t;l<=n;l+=1)a.push(`h${l}.anchor`);return Array.from(document.querySelectorAll(a.join()))}({minHeadingLevel:r,maxHeadingLevel:o}),c=s(i,{anchorTopOffset:n.current}),m=e.find((e=>c&&c.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(l),e.classList.add(l),t.current=e):e.classList.remove(l)}(e,e===m)}))}return document.addEventListener("scroll",i),document.addEventListener("resize",i),i(),()=>{document.removeEventListener("scroll",i),document.removeEventListener("resize",i)}}),[e,n])}function u(e){let{toc:t,className:n,linkClassName:a,isChild:r}=e;return t.length?l.createElement("ul",{className:r?void 0:n},t.map((e=>l.createElement("li",{key:e.id},l.createElement("a",{href:`#${e.id}`,className:a??void 0,dangerouslySetInnerHTML:{__html:e.value}}),l.createElement(u,{isChild:!0,toc:e.children,className:n,linkClassName:a}))))):null}const g=l.memo(u);function f(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:c="table-of-contents__link",linkActiveClassName:s,minHeadingLevel:m,maxHeadingLevel:u,...f}=e;const v=(0,r.L)(),p=m??v.tableOfContents.minHeadingLevel,h=u??v.tableOfContents.maxHeadingLevel,b=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,l.useMemo)((()=>i({toc:o(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:p,maxHeadingLevel:h});return d((0,l.useMemo)((()=>{if(c&&s)return{linkClassName:c,linkActiveClassName:s,minHeadingLevel:p,maxHeadingLevel:h}}),[c,s,p,h])),l.createElement(g,(0,a.Z)({toc:b,className:n,linkClassName:c},f))}}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/cd10b72d.4205b928.js b/pr-preview/pr-192/assets/js/cd10b72d.4205b928.js deleted file mode 100644 index 09f58c5fd..000000000 --- a/pr-preview/pr-192/assets/js/cd10b72d.4205b928.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6105],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var l=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);t&&(l=l.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,l)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function a(e,t){if(null==e)return{};var r,l,n=function(e,t){if(null==e)return{};var r,l,n={},o=Object.keys(e);for(l=0;l<o.length;l++)r=o[l],t.indexOf(r)>=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(l=0;l<o.length;l++)r=o[l],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var p=l.createContext({}),s=function(e){var t=l.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=s(e.components);return l.createElement(p.Provider,{value:t},e.children)},d="mdxType",c={inlineCode:"code",wrapper:function(e){var t=e.children;return l.createElement(l.Fragment,{},t)}},m=l.forwardRef((function(e,t){var r=e.components,n=e.mdxType,o=e.originalType,p=e.parentName,u=a(e,["components","mdxType","originalType","parentName"]),d=s(r),m=n,g=d["".concat(p,".").concat(m)]||d[m]||c[m]||o;return r?l.createElement(g,i(i({ref:t},u),{},{components:r})):l.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=r.length,i=new Array(o);i[0]=m;var a={};for(var p in t)hasOwnProperty.call(t,p)&&(a[p]=t[p]);a.originalType=e,a[d]="string"==typeof e?e:n,i[1]=a;for(var s=2;s<o;s++)i[s]=r[s];return l.createElement.apply(null,i)}return l.createElement.apply(null,r)}m.displayName="MDXCreateElement"},1801:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>s});var l=r(7462),n=(r(7294),r(3905));const o={sidebar_label:"Building & deploying a rollup",description:"Build sovereign Cosmos-SDK and EVM applications"},i="\ud83d\uddde\ufe0f Building a rollup and testnet deployment",a={unversionedId:"tutorials/building-and-deploying-a-rollup",id:"tutorials/building-and-deploying-a-rollup",title:"\ud83d\uddde\ufe0f Building a rollup and testnet deployment",description:"Build sovereign Cosmos-SDK and EVM applications",source:"@site/docs/tutorials/building-and-deploying-a-rollup.md",sourceDirName:"tutorials",slug:"/tutorials/building-and-deploying-a-rollup",permalink:"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/building-and-deploying-a-rollup.md",tags:[],version:"current",frontMatter:{sidebar_label:"Building & deploying a rollup",description:"Build sovereign Cosmos-SDK and EVM applications"},sidebar:"docs",previous:{title:"Beginner",permalink:"/pr-preview/pr-192/docs/category/beginner"},next:{title:"GM world tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/gm-world"}},p={},s=[{value:"\ud83d\udd30 Beginner",id:"-beginner",level:2},{value:"\ud83c\udfc3\u200d\u2642\ufe0f Intermediate",id:"\ufe0f-intermediate",level:2},{value:"\ud83d\udc8e Advanced",id:"-advanced",level:2},{value:"\ud83d\udcbb Support",id:"-support",level:2}],u={toc:s};function d(e){let{components:t,...r}=e;return(0,n.kt)("wrapper",(0,l.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"\ufe0f-building-a-rollup-and-testnet-deployment"},"\ud83d\uddde\ufe0f Building a rollup and testnet deployment"),(0,n.kt)("p",null,"The following tutorials will help you get started building\nCosmos-SDK and EVM applications that connect to Celestia's data availability\n(DA) layer via Rollkit to Celestia's\n",(0,n.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/mocha-testnet"},"Mocha testnet"),"\nor Arabica devnet. We call those chains Sovereign Rollups."),(0,n.kt)("p",null,"You can get started with the following tutorials:"),(0,n.kt)("h2",{id:"-beginner"},"\ud83d\udd30 Beginner"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/gm-world"},"GM world")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/recipe-book"},"Recipe book")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup"},"Restart your rollup"))),(0,n.kt)("h2",{id:"\ufe0f-intermediate"},"\ud83c\udfc3\u200d\u2642\ufe0f Intermediate"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"/pr-preview/pr-192/docs/tutorials/wordle"},"Wordle game")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://rollkit.dev/docs/tutorials/cosmwasm"},"CosmWasm rollup"))),(0,n.kt)("h2",{id:"-advanced"},"\ud83d\udc8e Advanced"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://rollkit.dev/docs/tutorials/ethermint"},"Ethermint rollup")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://docs.celestia.org/developers/full-stack-modular-development-guide"},"Full-stack modular dapp with Celestia")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("a",{parentName:"li",href:"https://docs.hyperlane.xyz/docs/deploy/celestia-+-hyperlane"},"Hyperlane + Celestia tutorial"))),(0,n.kt)("h2",{id:"-support"},"\ud83d\udcbb Support"),(0,n.kt)("p",null,"The tutorials will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"issue"),"\nor let us know in our ",(0,n.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),'.\nFurthermore, while Rollkit allows you to build sovereign rollups\non Celestia, it currently does not support fraud proofs yet and is\ntherefore running in "pessimistic" mode, where nodes would need to\nre-execute the transactions to check the validity of the chain\n(i.e. a full node). Furthermore, Rollkit currently only supports\na single sequencer.'))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/dbc9f6d7.98fdef6e.js b/pr-preview/pr-192/assets/js/dbc9f6d7.98fdef6e.js deleted file mode 100644 index 276a2cd36..000000000 --- a/pr-preview/pr-192/assets/js/dbc9f6d7.98fdef6e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[1074],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>h});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=c(n),f=o,h=p["".concat(s,".").concat(f)]||p[f]||d[f]||a;return n?r.createElement(h,i(i({ref:t},u),{},{components:n})):r.createElement(h,i({ref:t},u))}));function h(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:o,i[1]=l;for(var c=2;c<a;c++)i[c]=n[c];return r.createElement.apply(null,i)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},4333:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var r=n(7462),o=(n(7294),n(3905));const a={sidebar_label:"Transaction flow",description:"Description of the flow of the Rollkit transaction."},i="Transaction flow",l={unversionedId:"transaction-flow",id:"transaction-flow",title:"Transaction flow",description:"Description of the flow of the Rollkit transaction.",source:"@site/docs/transaction-flow.md",sourceDirName:".",slug:"/transaction-flow",permalink:"/pr-preview/pr-192/docs/transaction-flow",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/transaction-flow.md",tags:[],version:"current",frontMatter:{sidebar_label:"Transaction flow",description:"Description of the flow of the Rollkit transaction."},sidebar:"docs",previous:{title:"Rollkit stack",permalink:"/pr-preview/pr-192/docs/rollkit-stack"},next:{title:"Tutorials",permalink:"/pr-preview/pr-192/docs/category/tutorials"}},s={},c=[],u={toc:c};function p(e){let{components:t,...a}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"transaction-flow"},"Transaction flow"),(0,o.kt)("p",null,"Rollup users use a light node to communicate with the rollup P2P network for two primary reasons:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"submiting transactions"),(0,o.kt)("li",{parentName:"ul"},"gossipping headers and fraud proofs")),(0,o.kt)("admonition",{title:"note",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Light nodes are still a work in progress.")),(0,o.kt)("p",null,"Here's what the typical transaction flow looks like:"),(0,o.kt)("p",null,(0,o.kt)("img",{alt:"tx-flow",src:n(1930).Z,width:"3901",height:"3263"})),(0,o.kt)("p",null,"To transact, users submit a transaction to their light node, which gossips the transaction to a full node. Before adding the transaction to their mempool, the full node checks its validity. Valid transactions are included in the mempool, while invalid ones are refused, and the user's transaction will not be processed."),(0,o.kt)("p",null,"If the transaction is valid and has been included in the mempool, the sequencer can add it to a rollup block, which is then submitted to the data availability (DA) layer. This results in a successful transaction flow for the user, and the state of the rollup is updated accordingly."),(0,o.kt)("p",null,"After the block is submitted to the DA layer, the full nodes download and validate the block.\nHowever, there is a possibility that the sequencer may maliciously submit a block to the DA layer with invalid transactions or state. In such cases, the full nodes of the rollup chain will consider the block invalid. In the case of an optimistic rollup, if they find the block invalid, they generate fraud proofs and gossip them in the P2P network among other full and light nodes."),(0,o.kt)("p",null,"As a result, the rollup chain will halt, and the network will decide to fork the chain through social consensus. In the future, when a decentralized sequencer scheme is in place, additional options will be available, such as slashing the sequencer or selecting another full node as the sequencer. However, in any case, a new block must be created and submitted to the DA layer. You can read more about sequencer nodes ",(0,o.kt)("a",{parentName:"p",href:"/pr-preview/pr-192/docs/rollkit-stack#sequencer-node"},"here"),"."))}p.isMDXComponent=!0},1930:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/transaction-flow-b70c673856a2495140120f52b31867ef.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/ddc2e5d7.2e885599.js b/pr-preview/pr-192/assets/js/ddc2e5d7.2e885599.js deleted file mode 100644 index e66820afa..000000000 --- a/pr-preview/pr-192/assets/js/ddc2e5d7.2e885599.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8714],{3905:(t,e,i)=>{i.d(e,{Zo:()=>p,kt:()=>m});var o=i(7294);function a(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function n(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);e&&(o=o.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,o)}return i}function l(t){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{};e%2?n(Object(i),!0).forEach((function(e){a(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):n(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function r(t,e){if(null==t)return{};var i,o,a=function(t,e){if(null==t)return{};var i,o,a={},n=Object.keys(t);for(o=0;o<n.length;o++)i=n[o],e.indexOf(i)>=0||(a[i]=t[i]);return a}(t,e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);for(o=0;o<n.length;o++)i=n[o],e.indexOf(i)>=0||Object.prototype.propertyIsEnumerable.call(t,i)&&(a[i]=t[i])}return a}var s=o.createContext({}),c=function(t){var e=o.useContext(s),i=e;return t&&(i="function"==typeof t?t(e):l(l({},e),t)),i},p=function(t){var e=c(t.components);return o.createElement(s.Provider,{value:e},t.children)},d="mdxType",u={inlineCode:"code",wrapper:function(t){var e=t.children;return o.createElement(o.Fragment,{},e)}},h=o.forwardRef((function(t,e){var i=t.components,a=t.mdxType,n=t.originalType,s=t.parentName,p=r(t,["components","mdxType","originalType","parentName"]),d=c(i),h=a,m=d["".concat(s,".").concat(h)]||d[h]||u[h]||n;return i?o.createElement(m,l(l({ref:e},p),{},{components:i})):o.createElement(m,l({ref:e},p))}));function m(t,e){var i=arguments,a=e&&e.mdxType;if("string"==typeof t||a){var n=i.length,l=new Array(n);l[0]=h;var r={};for(var s in e)hasOwnProperty.call(e,s)&&(r[s]=e[s]);r.originalType=t,r[d]="string"==typeof t?t:a,l[1]=r;for(var c=2;c<n;c++)l[c]=i[c];return o.createElement.apply(null,l)}return o.createElement.apply(null,i)}h.displayName="MDXCreateElement"},1275:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>n,metadata:()=>r,toc:()=>c});var o=i(7462),a=(i(7294),i(3905));const n={slug:"sovereign-rollups-on-bitcoin",title:"Sovereign rollups on Bitcoin with Rollkit",authors:["rollkit"],tags:["Rollkit","Bitcoin"],description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it."},l=void 0,r={permalink:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin",editUrl:"https://github.com/rollkit/docs/tree/main/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx",source:"@site/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx",title:"Sovereign rollups on Bitcoin with Rollkit",description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it.",date:"2023-03-05T00:00:00.000Z",formattedDate:"March 5, 2023",tags:[{label:"Rollkit",permalink:"/pr-preview/pr-192/blog/tags/rollkit"},{label:"Bitcoin",permalink:"/pr-preview/pr-192/blog/tags/bitcoin"}],readingTime:4.32,hasTruncateMarker:!1,authors:[{name:"Rollkit",url:"https://github.com/rollkit",imageURL:"https://github.com/rollkit.png",key:"rollkit"}],frontMatter:{slug:"sovereign-rollups-on-bitcoin",title:"Sovereign rollups on Bitcoin with Rollkit",authors:["rollkit"],tags:["Rollkit","Bitcoin"],description:"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. This allows Rollkit rollups to use Bitcoin for data availability. The implementation is in alpha, but we invite curious developers to experiment with it."},prevItem:{title:"Let's Roll - Rollkit's community call",permalink:"/pr-preview/pr-192/blog/lets-roll-community-call"},nextItem:{title:"Introducing Rollkit: a modular rollup framework",permalink:"/pr-preview/pr-192/blog/introducing-rollkit"}},s={authorsImageUrls:[void 0]},c=[{value:"Tl;dr",id:"tldr",level:2},{value:"Posting data on Bitcoin with Taproot",id:"posting-data-on-bitcoin-with-taproot",level:2},{value:"Integrating Bitcoin as a data availability layer into Rollkit",id:"integrating-bitcoin-as-a-data-availability-layer-into-rollkit",level:2},{value:"How Rollkit posts data to Bitcoin",id:"how-rollkit-posts-data-to-bitcoin",level:2},{value:"EVM on Bitcoin demo",id:"evm-on-bitcoin-demo",level:2},{value:"Conclusion",id:"conclusion",level:2}],p={toc:c};function d(t){let{components:e,...n}=t;return(0,a.kt)("wrapper",(0,o.Z)({},p,n,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin",src:i(2223).Z,width:"3000",height:"1500"})),(0,a.kt)("p",null,"Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability."),(0,a.kt)("p",null,"Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin\u2019s data availability guarantees and re-org resistance. With the new integration it is now possible to run the ",(0,a.kt)("a",{parentName:"p",href:"/docs/tutorials/bitcoin"},"EVM on Bitcoin as a Rollkit sovereign rollup"),". Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget."),(0,a.kt)("h2",{id:"tldr"},"Tl;dr"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit\u2019s new early research integration."),(0,a.kt)("li",{parentName:"ul"},"Follow along with a ",(0,a.kt)("a",{parentName:"li",href:"#evm-on-bitcoin-demo"},"demo")," of the EVM running on Bitcoin as a sovereign Rollkit rollup."),(0,a.kt)("li",{parentName:"ul"},"The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.")),(0,a.kt)("h2",{id:"posting-data-on-bitcoin-with-taproot"},"Posting data on Bitcoin with Taproot"),(0,a.kt)("p",null,"On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with ",(0,a.kt)("a",{parentName:"p",href:"https://ordinals.com/"},"Ordinals"),", a project that implements NFTs on Bitcoin by publishing the image data on-chain."),(0,a.kt)("p",null,"Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain."),(0,a.kt)("p",null,"Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has ",(0,a.kt)("a",{parentName:"p",href:"https://dune.com/dataalways/ordinals"},"kicked off"),". Eric Wall found that at the time of ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/ercwl/status/1619671451417862145"},"his tweet"),", posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer."),(0,a.kt)("h2",{id:"integrating-bitcoin-as-a-data-availability-layer-into-rollkit"},"Integrating Bitcoin as a data availability layer into Rollkit"),(0,a.kt)("p",null,"Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin-rollup",src:i(2626).Z,width:"3000",height:"2708"})),(0,a.kt)("h2",{id:"how-rollkit-posts-data-to-bitcoin"},"How Rollkit posts data to Bitcoin"),(0,a.kt)("p",null,"To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/bitcoin-da"},"a Go package called ",(0,a.kt)("inlineCode",{parentName:"a"},"bitcoin-da"))," that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit-btc/blob/main/spec.md"},"the specs"),". The package can be re-used by any project that wants to read or write data on Bitcoin."),(0,a.kt)("p",null,"Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the ",(0,a.kt)("inlineCode",{parentName:"p"},"DataAvailabilityLayerClient")," interface which defines the behavior of the data availability client, and the ",(0,a.kt)("inlineCode",{parentName:"p"},"BlockRetriever")," interface which defines how blocks can be synced. These interfaces live in the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/rollkit/rollkit/tree/main/da"},"da package"),". The most important methods in these interfaces are ",(0,a.kt)("inlineCode",{parentName:"p"},"SubmitBlock")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"RetrieveBlock")," for reading and writing the blocks."),(0,a.kt)("p",null,"After implementing the Taproot reader/writer interface for Bitcoin (",(0,a.kt)("inlineCode",{parentName:"p"},"bitcoin-da"),"), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the ",(0,a.kt)("inlineCode",{parentName:"p"},"SubmitBlock")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"RetrieveBlocks")," functions for Rollkit to call the ",(0,a.kt)("inlineCode",{parentName:"p"},"Read")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"Write")," methods in ",(0,a.kt)("inlineCode",{parentName:"p"},"bitcoin-da"),"."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"rollkit-bitcoin-rollup-2",src:i(2622).Z,width:"3000",height:"1415"})),(0,a.kt)("h2",{id:"evm-on-bitcoin-demo"},"EVM on Bitcoin demo"),(0,a.kt)("p",null,"Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo."),(0,a.kt)("div",{class:"youtube-wrapper"},(0,a.kt)("iframe",{class:"youtube-video",title:"Rollkit: Ethermint + Bitcoin DA demo",src:"https://www.youtube.com/embed/qBKFEctzgT0",allowfullscreen:!0})),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. ",(0,a.kt)("a",{parentName:"p",href:"https://blog.celestia.org/sovereign-rollup-chains/"},"Sovereign rollups")," fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin."),(0,a.kt)("p",null,"Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions ",(0,a.kt)("a",{parentName:"p",href:"/docs/tutorials/bitcoin"},"here"),". Keep in mind that the integration is an early research implementation and it is not yet production-ready!"),(0,a.kt)("p",null,"Modularism, not maximalism."))}d.isMDXComponent=!0},2626:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-1-4fdcb47746b24626aed8f6689035a4b7.png"},2622:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-2-e97ee76fdc66279cd58e7e27177fcdb0.png"},2223:(t,e,i)=>{i.d(e,{Z:()=>o});const o=i.p+"assets/images/rollkit-bitcoin-7bcecada0c85b79bf2b58ed20980d43c.png"}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/e8a90596.85177f7f.js b/pr-preview/pr-192/assets/js/e8a90596.85177f7f.js deleted file mode 100644 index 247ec5b44..000000000 --- a/pr-preview/pr-192/assets/js/e8a90596.85177f7f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5986],{4885:e=>{e.exports=JSON.parse('{"title":"Intermediate","slug":"/category/intermediate","permalink":"/pr-preview/pr-192/docs/category/intermediate","navigation":{"previous":{"title":"How to restart your rollup","permalink":"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup"},"next":{"title":"Wordle tutorial","permalink":"/pr-preview/pr-192/docs/tutorials/wordle"}}}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/ea3e41d5.ec8db3d9.js b/pr-preview/pr-192/assets/js/ea3e41d5.ec8db3d9.js deleted file mode 100644 index 2b65ad3f5..000000000 --- a/pr-preview/pr-192/assets/js/ea3e41d5.ec8db3d9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[5842],{3905:(e,t,a)=>{a.d(t,{Zo:()=>m,kt:()=>h});var n=a(7294);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function r(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?s(Object(a),!0).forEach((function(t){o(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):s(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function i(e,t){if(null==e)return{};var a,n,o=function(e,t){if(null==e)return{};var a,n,o={},s=Object.keys(e);for(n=0;n<s.length;n++)a=s[n],t.indexOf(a)>=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n<s.length;n++)a=s[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var l=n.createContext({}),c=function(e){var t=n.useContext(l),a=t;return e&&(a="function"==typeof e?e(t):r(r({},t),e)),a},m=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var a=e.components,o=e.mdxType,s=e.originalType,l=e.parentName,m=i(e,["components","mdxType","originalType","parentName"]),u=c(a),d=o,h=u["".concat(l,".").concat(d)]||u[d]||p[d]||s;return a?n.createElement(h,r(r({ref:t},m),{},{components:a})):n.createElement(h,r({ref:t},m))}));function h(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var s=a.length,r=new Array(s);r[0]=d;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[u]="string"==typeof e?e:o,r[1]=i;for(var c=2;c<s;c++)r[c]=a[c];return n.createElement.apply(null,r)}return n.createElement.apply(null,a)}d.displayName="MDXCreateElement"},5162:(e,t,a)=>{a.d(t,{Z:()=>r});var n=a(7294),o=a(6010);const s="tabItem_Ymn6";function r(e){let{children:t,hidden:a,className:r}=e;return n.createElement("div",{role:"tabpanel",className:(0,o.Z)(s,r),hidden:a},t)}},5488:(e,t,a)=>{a.d(t,{Z:()=>d});var n=a(7462),o=a(7294),s=a(6010),r=a(2389),i=a(7392),l=a(7094),c=a(2466);const m="tabList__CuJ",u="tabItem_LNqP";function p(e){const{lazy:t,block:a,defaultValue:r,values:p,groupId:d,className:h}=e,w=o.Children.map(e.children,(e=>{if((0,o.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad <Tabs> child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`)})),k=p??w.map((e=>{let{props:{value:t,label:a,attributes:n}}=e;return{value:t,label:a,attributes:n}})),g=(0,i.l)(k,((e,t)=>e.value===t.value));if(g.length>0)throw new Error(`Docusaurus error: Duplicate values "${g.map((e=>e.value)).join(", ")}" found in <Tabs>. Every value needs to be unique.`);const f=null===r?r:r??w.find((e=>e.props.default))?.props.value??w[0].props.value;if(null!==f&&!k.some((e=>e.value===f)))throw new Error(`Docusaurus error: The <Tabs> has a defaultValue "${f}" but none of its children has the corresponding value. Available values are: ${k.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);const{tabGroupChoices:b,setTabGroupChoices:v}=(0,l.U)(),[y,N]=(0,o.useState)(f),C=[],{blockElementScrollPositionUntilNextRender:T}=(0,c.o5)();if(null!=d){const e=b[d];null!=e&&e!==y&&k.some((t=>t.value===e))&&N(e)}const _=e=>{const t=e.currentTarget,a=C.indexOf(t),n=k[a].value;n!==y&&(T(t),N(n),null!=d&&v(d,String(n)))},E=e=>{let t=null;switch(e.key){case"Enter":_(e);break;case"ArrowRight":{const a=C.indexOf(e.currentTarget)+1;t=C[a]??C[0];break}case"ArrowLeft":{const a=C.indexOf(e.currentTarget)-1;t=C[a]??C[C.length-1];break}}t?.focus()};return o.createElement("div",{className:(0,s.Z)("tabs-container",m)},o.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,s.Z)("tabs",{"tabs--block":a},h)},k.map((e=>{let{value:t,label:a,attributes:r}=e;return o.createElement("li",(0,n.Z)({role:"tab",tabIndex:y===t?0:-1,"aria-selected":y===t,key:t,ref:e=>C.push(e),onKeyDown:E,onClick:_},r,{className:(0,s.Z)("tabs__item",u,r?.className,{"tabs__item--active":y===t})}),a??t)}))),t?(0,o.cloneElement)(w.filter((e=>e.props.value===y))[0],{className:"margin-top--md"}):o.createElement("div",{className:"margin-top--md"},w.map(((e,t)=>(0,o.cloneElement)(e,{key:t,hidden:e.props.value!==y})))))}function d(e){const t=(0,r.Z)();return o.createElement(p,(0,n.Z)({key:String(t)},e))}},8169:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>m,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>u});var n=a(7462),o=(a(7294),a(3905)),s=a(5488),r=a(5162);const i={sidebar_label:"CosmWasm tutorial",description:"Build a sovereign rollup with CosmWasm, Celestia, and Rollkit"},l="\ud83d\uddde\ufe0f CosmWasm rollup",c={unversionedId:"tutorials/cosmwasm",id:"tutorials/cosmwasm",title:"\ud83d\uddde\ufe0f CosmWasm rollup",description:"Build a sovereign rollup with CosmWasm, Celestia, and Rollkit",source:"@site/docs/tutorials/cosmwasm.md",sourceDirName:"tutorials",slug:"/tutorials/cosmwasm",permalink:"/pr-preview/pr-192/docs/tutorials/cosmwasm",draft:!1,editUrl:"https://github.com/rollkit/docs/tree/main/docs/tutorials/cosmwasm.md",tags:[],version:"current",frontMatter:{sidebar_label:"CosmWasm tutorial",description:"Build a sovereign rollup with CosmWasm, Celestia, and Rollkit"},sidebar:"docs",previous:{title:"Wordle tutorial",permalink:"/pr-preview/pr-192/docs/tutorials/wordle"},next:{title:"Advanced",permalink:"/pr-preview/pr-192/docs/category/advanced"}},m={},u=[{value:"\ud83d\udcbb CosmWasm dependency installations",id:"-cosmwasm-dependency-installations",level:2},{value:"\ud83d\udee0\ufe0f Environment setup",id:"\ufe0f-environment-setup",level:3},{value:"\ud83c\udfc3 Golang dependency",id:"-golang-dependency",level:3},{value:"\ud83e\udd80 Rust installation",id:"-rust-installation",level:3},{value:"\ud83d\udd28 Rustup",id:"-rustup",level:4},{value:"\ud83d\udc33 Docker installation",id:"-docker-installation",level:3},{value:"\ud83d\udcbb Wasmd installation",id:"-wasmd-installation",level:3},{value:"\u2728 Celestia node",id:"-celestia-node",level:3},{value:"\ud83c\udf0c Setting up your environment for CosmWasm on Celestia",id:"-setting-up-your-environment-for-cosmwasm-on-celestia",level:2},{value:"\ud83d\uddde\ufe0f Initializing CosmWasm rollup with a bash script",id:"\ufe0f-initializing-cosmwasm-rollup-with-a-bash-script",level:3},{value:"\ud83d\udca0 Optional: see what's inside the script",id:"-optional-see-whats-inside-the-script",level:3},{value:"\ud83d\udcd2 Contract deployment on CosmWasm with Rollkit",id:"-contract-deployment-on-cosmwasm-with-rollkit",level:2},{value:"\ud83e\udd16 Compile the smart contract",id:"-compile-the-smart-contract",level:3},{value:"\ud83e\uddea Unit tests",id:"-unit-tests",level:3},{value:"\ud83c\udfce\ufe0f Optimized smart contract",id:"\ufe0f-optimized-smart-contract",level:3},{value:"AMD Machines",id:"amd-machines",level:3},{value:"ARM Machines",id:"arm-machines",level:3},{value:"\ud83d\ude80 Contract deployment",id:"-contract-deployment",level:3},{value:"AMD Machines",id:"amd-machines-1",level:3},{value:"ARM Machines",id:"arm-machines-1",level:3},{value:"\ud83c\udf1f Contract interaction on CosmWasm with Celestia",id:"-contract-interaction-on-cosmwasm-with-celestia",level:2},{value:"\ud83d\udd0e Contract querying",id:"-contract-querying",level:3},{value:"\ud83d\udcc3 Contract instantiation",id:"-contract-instantiation",level:3},{value:"\ud83d\udcc4 Contract interaction",id:"-contract-interaction",level:3}],p={toc:u};function d(e){let{components:t,...a}=e;return(0,o.kt)("wrapper",(0,n.Z)({},p,a,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"\ufe0f-cosmwasm-rollup"},"\ud83d\uddde\ufe0f CosmWasm rollup"),(0,o.kt)("p",null,"CosmWasm is a smart contracting platform built for the Cosmos\necosystem by making use of ",(0,o.kt)("a",{parentName:"p",href:"https://webassembly.org"},"WebAssembly")," (Wasm)\nto build smart contracts for Cosmos-SDK. In this tutorial, we will be\nexploring how to integrate CosmWasm with Celestia's\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/concepts/how-celestia-works/data-availability-layer"},"data availability layer"),"\nusing Rollkit."),(0,o.kt)("admonition",{title:"note",type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"This tutorial will explore developing with Rollkit,\nwhich is still in Alpha stage. If you run into bugs, please write a Github\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/issues/new"},"Issue ticket"),"\nor let us know in our ",(0,o.kt)("a",{parentName:"p",href:"https://t.me/rollkit"},"Telegram"),".")),(0,o.kt)("admonition",{title:"caution",type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"The script for this tutorial is built for Celestia's\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspacerace testnet"),".\nIf you choose to use Mocha testnet or Arabica devnet,\nyou will need to modify the script manually.")),(0,o.kt)("p",null,"You can learn more about CosmWasm ",(0,o.kt)("a",{parentName:"p",href:"https://docs.cosmwasm.com/docs/"},"here"),"."),(0,o.kt)("p",null,"In this tutorial, we will going over the following:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#setting-up-your-environment-for-cosmwasm-on-celestia"},"Setting up your dependencies for your CosmWasm smart contracts")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#wasmd-installation"},"Setting up Rollkit on CosmWasm")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#contract-interaction-on-cosmwasm-with-celestia"},"Instantiate a local network for your CosmWasm chain connected to Celestia")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#contract-deployment-on-cosmwasm-with-rollkit"},"Deploying a Rust smart contract to CosmWasm chain")),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("a",{parentName:"li",href:"#contract-interaction-on-cosmwasm-with-celestia"},"Interacting with the smart contract"))),(0,o.kt)("p",null,"The smart contract we will use for this tutorial is one provided by\nthe CosmWasm team for Nameservice purchasing."),(0,o.kt)("p",null,"You can check out the contract ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/InterWasm/cw-contracts/tree/main/contracts/nameservice"},"here"),"."),(0,o.kt)("p",null,"How to write the Rust smart contract for Nameservice is outside the scope of\nthis tutorial. In the future we will add more tutorials for writing CosmWasm\nsmart contracts for Celestia."),(0,o.kt)("h2",{id:"-cosmwasm-dependency-installations"},"\ud83d\udcbb CosmWasm dependency installations"),(0,o.kt)("h3",{id:"\ufe0f-environment-setup"},"\ud83d\udee0\ufe0f Environment setup"),(0,o.kt)("p",null,"For this tutorial, we will be using ",(0,o.kt)("inlineCode",{parentName:"p"},"curl")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"jq")," as helpful\ntools. You can follow the guide on installing them\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment/#-install-wget-and-jq"},"here"),"."),(0,o.kt)("h3",{id:"-golang-dependency"},"\ud83c\udfc3 Golang dependency"),(0,o.kt)("p",null,"The Golang version used for this tutorial is v1.18+"),(0,o.kt)("p",null,"You can install Golang\nby following our tutorial ",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/environment#install-golang"},"here"),"."),(0,o.kt)("h3",{id:"-rust-installation"},"\ud83e\udd80 Rust installation"),(0,o.kt)("h4",{id:"-rustup"},"\ud83d\udd28 Rustup"),(0,o.kt)("p",null,"First, before installing Rust, you would need to install ",(0,o.kt)("inlineCode",{parentName:"p"},"rustup"),"."),(0,o.kt)("p",null,"On Mac and Linux systems, here are the commands for installing it:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n")),(0,o.kt)("admonition",{title:"caution",type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"You will see a note similar to below after installing Rust:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'Rust is installed now. Great!\n\nTo get started you may need to restart your current shell.\nThis would reload your PATH environment variable to include\nCargo\'s bin directory ($HOME/.cargo/bin).\n\nTo configure your current shell, run:\nsource "$HOME/.cargo/env"\n')),(0,o.kt)("p",{parentName:"admonition"},"If you don't follow the guidance, you won't be able to continue with the\ntutorial!")),(0,o.kt)("p",null,"After installation, follow the commands here to setup Rust."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"rustup default stable\ncargo version\n\nrustup target list --installed\nrustup target add wasm32-unknown-unknown\n")),(0,o.kt)("p",null,"Your output should look similar to below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"info: using existing install for 'stable-aarch64-apple-darwin'\ninfo: default toolchain set to 'stable-aarch64-apple-darwin'\n\n stable-aarch64-apple-darwin unchanged - rustc 1.65.0 (897e37553 2022-11-02)\n \ncargo 1.65.0 (4bc8f24d3 2022-10-20)\naarch64-apple-darwin\ninfo: downloading component 'rust-std' for 'wasm32-unknown-unknown'\ninfo: installing component 'rust-std' for 'wasm32-unknown-unknown'\n")),(0,o.kt)("h3",{id:"-docker-installation"},"\ud83d\udc33 Docker installation"),(0,o.kt)("p",null,"We will be using Docker later in this tutorial for compiling a smart contract\nto use a small footprint. We recommend installing Docker on your machine."),(0,o.kt)("p",null,"Examples on how to install it on Linux are found ",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/install/ubuntu"},"here"),".\nFind the right instructions specific for\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.docker.com/engine/install"},"your OS here"),"."),(0,o.kt)("h3",{id:"-wasmd-installation"},"\ud83d\udcbb Wasmd installation"),(0,o.kt)("p",null,"Here, we are going to pull down the ",(0,o.kt)("inlineCode",{parentName:"p"},"wasmd")," repository and replace Tendermint\nwith Rollkit. Rollkit is a drop-in replacement for Tendermint that allows\nCosmos-SDK applications to connect to Celestia's data availability network."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"git clone https://github.com/CosmWasm/wasmd.git\ncd wasmd\ngit fetch --tags\ngit checkout v0.27.0\ngo mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.45.10-rollkit-v0.7.3-no-fraud-proofs\ngo mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d\ngo mod tidy -compat=1.17\ngo mod download\nmake install\n")),(0,o.kt)("h3",{id:"-celestia-node"},"\u2728 Celestia node"),(0,o.kt)("p",null,"You will need a light node running with test tokens on\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/nodes/blockspace-race"},"Blockspace race testnet")," in order\nto complete this tutorial. Please complete the tutorial\n",(0,o.kt)("a",{parentName:"p",href:"https://docs.celestia.org/developers/node-tutorial"},"here"),",\nor start up your node."),(0,o.kt)("h2",{id:"-setting-up-your-environment-for-cosmwasm-on-celestia"},"\ud83c\udf0c Setting up your environment for CosmWasm on Celestia"),(0,o.kt)("p",null,"Now the ",(0,o.kt)("inlineCode",{parentName:"p"},"wasmd")," binary is built, we need to setup a local network\nthat communicates between ",(0,o.kt)("inlineCode",{parentName:"p"},"wasmd")," and Rollkit."),(0,o.kt)("h3",{id:"\ufe0f-initializing-cosmwasm-rollup-with-a-bash-script"},"\ud83d\uddde\ufe0f Initializing CosmWasm rollup with a bash script"),(0,o.kt)("p",null,"We have a handy ",(0,o.kt)("inlineCode",{parentName:"p"},"init.sh")," found in this repo\n",(0,o.kt)("a",{parentName:"p",href:"https://github.com/rollkit/docs/tree/main/docs/scripts/cosmwasm"},"here"),"."),(0,o.kt)("p",null,"We can copy it over to our directory with the following commands:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"# From inside the `wasmd` directory\nwget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/cosmwasm/init.sh\n")),(0,o.kt)("p",null,"This copies over our ",(0,o.kt)("inlineCode",{parentName:"p"},"init.sh")," script to initialize our\nCosmWasm rollup."),(0,o.kt)("p",null,"You can view the contents of the script to see how we\ninitialize the CosmWasm Rollup."),(0,o.kt)("p",null,"You can initialize the script with the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"bash init.sh\n")),(0,o.kt)("p",null,"With that, we have kickstarted our ",(0,o.kt)("inlineCode",{parentName:"p"},"wasmd")," network!"),(0,o.kt)("h3",{id:"-optional-see-whats-inside-the-script"},"\ud83d\udca0 Optional: see what's inside the script"),(0,o.kt)("p",null,"You can skip this section, but it is important to know\nhow Rollkit is initializing the cosmwasm rollup."),(0,o.kt)("p",null,"Here are the contents of the script:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'#!/bin/sh\n\nVALIDATOR_NAME=validator1\nCHAIN_ID=celeswasm\nKEY_NAME=celeswasm-key\nTOKEN_AMOUNT="10000000000000000000000000uwasm"\nSTAKING_AMOUNT=1000000000uwasm\nCHAINFLAG="--chain-id ${CHAIN_ID}"\nTXFLAG="--chain-id ${CHAIN_ID} --gas-prices 0uwasm --gas auto --gas-adjustment 1.3"\n\nNAMESPACE_ID=$(openssl rand -hex 8)\necho $NAMESPACE_ID\nDA_BLOCK_HEIGHT=$(curl https://rpc-mocha.pops.one/block | jq -r \'.result.block.header.height\')\necho $DA_BLOCK_HEIGHT\n\nrm -rf "$HOME"/.wasmd\nwasmd tendermint unsafe-reset-all\nwasmd init $VALIDATOR_NAME --chain-id $CHAIN_ID\n\nsed -i\'\' -e \'s/^minimum-gas-prices *= .*/minimum-gas-prices = "0uwasm"/\' "$HOME"/.wasmd/config/app.toml\nsed -i\'\' -e \'/\\[api\\]/,+3 s/enable *= .*/enable = true/\' "$HOME"/.wasmd/config/app.toml\nsed -i\'\' -e "s/^chain-id *= .*/chain-id = \\"$CHAIN_ID\\"/" "$HOME"/.wasmd/config/client.toml\nsed -i\'\' -e \'/\\[rpc\\]/,+3 s/laddr *= .*/laddr = "tcp:\\/\\/0.0.0.0:26657"/\' "$HOME"/.wasmd/config/config.toml\nsed -i\'\' -e \'s/"time_iota_ms": "1000"/"time_iota_ms": "10"/\' "$HOME"/.wasmd/config/genesis.json\nsed -i\'\' -e \'s/bond_denom": ".*"/bond_denom": "uwasm"/\' "$HOME"/.wasmd/config/genesis.json\nsed -i\'\' -e \'s/mint_denom": ".*"/mint_denom": "uwasm"/\' "$HOME"/.wasmd/config/genesis.json\n\nwasmd keys add $KEY_NAME --keyring-backend test\nwasmd add-genesis-account $KEY_NAME $TOKEN_AMOUNT --keyring-backend test\nwasmd gentx $KEY_NAME $STAKING_AMOUNT --chain-id $CHAIN_ID --keyring-backend test\nwasmd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config=\'{"base_url":"http://localhost:26659","timeout":60000000000,"fee":6000,"gas_limit":6000000}\' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height $DA_BLOCK_HEIGHT\n')),(0,o.kt)("h2",{id:"-contract-deployment-on-cosmwasm-with-rollkit"},"\ud83d\udcd2 Contract deployment on CosmWasm with Rollkit"),(0,o.kt)("h3",{id:"-compile-the-smart-contract"},"\ud83e\udd16 Compile the smart contract"),(0,o.kt)("p",null,"In a new terminal instance, we will run the following commands to pull down the\nNameservice smart contract and compile it:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"git clone https://github.com/InterWasm/cw-contracts\ncd cw-contracts\ncd contracts/nameservice\ncargo wasm\n")),(0,o.kt)("p",null,"The compiled contract is outputted to:\n",(0,o.kt)("inlineCode",{parentName:"p"},"target/wasm32-unknown-unknown/release/cw_nameservice.wasm"),"."),(0,o.kt)("h3",{id:"-unit-tests"},"\ud83e\uddea Unit tests"),(0,o.kt)("p",null,"If we want to run tests, we can do so with the following command in the\n",(0,o.kt)("inlineCode",{parentName:"p"},"~/cw-contracts/contracts/nameservice")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"cargo unit-test\n")),(0,o.kt)("h3",{id:"\ufe0f-optimized-smart-contract"},"\ud83c\udfce\ufe0f Optimized smart contract"),(0,o.kt)("p",null,"Because we are deploying the compiled smart contract to ",(0,o.kt)("inlineCode",{parentName:"p"},"wasmd"),",\nwe want it to be as small as possible."),(0,o.kt)("p",null,"The CosmWasm team provides a tool called ",(0,o.kt)("inlineCode",{parentName:"p"},"rust-optimizer")," which we need\n",(0,o.kt)("a",{parentName:"p",href:"#docker-installation"},"Docker")," for in order to compile."),(0,o.kt)(s.Z,{groupId:"network",mdxType:"Tabs"},(0,o.kt)(r.Z,{value:"amd",label:"AMD",mdxType:"TabItem"},(0,o.kt)("h3",{id:"amd-machines"},"AMD Machines"),(0,o.kt)("p",null,"Run the following command in the ",(0,o.kt)("inlineCode",{parentName:"p"},"~/cw-contracts/contracts/nameservice"),"\ndirectory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'sudo docker run --rm -v "$(pwd)":/code \\\n --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \\\n --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \\\n cosmwasm/rust-optimizer:0.12.6\n')),(0,o.kt)("p",null,"This will place the optimized Wasm bytecode at ",(0,o.kt)("inlineCode",{parentName:"p"},"artifacts/cw_nameservice.wasm"),".")),(0,o.kt)(r.Z,{value:"arm",label:"ARM",mdxType:"TabItem"},(0,o.kt)("h3",{id:"arm-machines"},"ARM Machines"),(0,o.kt)("p",null,"Run the following command in the ",(0,o.kt)("inlineCode",{parentName:"p"},"~/cw-contracts/contracts/nameservice"),"\ndirectory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'sudo docker run --platform linux/arm64 --rm -v "$(pwd)":/code \\\n --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \\\n --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \\\n cosmwasm/rust-optimizer-arm64:0.12.8\n')),(0,o.kt)("p",null,"This will place the optimized Wasm bytecode at ",(0,o.kt)("inlineCode",{parentName:"p"},"artifacts/cw_nameservice-aarch64.wasm"),"."))),(0,o.kt)("h3",{id:"-contract-deployment"},"\ud83d\ude80 Contract deployment"),(0,o.kt)("p",null,"Let's now deploy our smart contract!"),(0,o.kt)(s.Z,{groupId:"network",mdxType:"Tabs"},(0,o.kt)(r.Z,{value:"amd",label:"AMD",mdxType:"TabItem"},(0,o.kt)("h3",{id:"amd-machines-1"},"AMD Machines"),(0,o.kt)("p",null,"Run the following in the ",(0,o.kt)("inlineCode",{parentName:"p"},"~/cw-contracts/contracts/nameservice")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"TX_HASH=$(wasmd tx wasm store artifacts/cw_nameservice.wasm --from celeswasm-key --keyring-backend test --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 --node http://127.0.0.1:26657 --output json -y | jq -r '.txhash') && echo $TX_HASH\n"))),(0,o.kt)(r.Z,{value:"arm",label:"ARM",mdxType:"TabItem"},(0,o.kt)("h3",{id:"arm-machines-1"},"ARM Machines"),(0,o.kt)("p",null,"Run the following in the ",(0,o.kt)("inlineCode",{parentName:"p"},"~/cw-contracts/contracts/nameservice")," directory:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"TX_HASH=$(wasmd tx wasm store artifacts/cw_nameservice-aarch64.wasm --from celeswasm-key --keyring-backend test --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 --node http://127.0.0.1:26657 --output json -y | jq -r '.txhash') && echo $TX_HASH\n")))),(0,o.kt)("p",null,"This will get you the transaction hash for the smart contract deployment. Given\nwe are using Rollkit, there will be a delay on the transaction being included\ndue to Rollkit waiting on Celestia's data availability layer to confirm the block\nhas been included before submitting a new block."),(0,o.kt)("admonition",{title:"important",type:"danger"},(0,o.kt)("p",{parentName:"admonition"},"If you run into errors with variables on the previous command,\nor commands in the remainder of the tutorial, cross-reference\nthe variables in the command with the variables in the ",(0,o.kt)("inlineCode",{parentName:"p"},"init.sh")," script.")),(0,o.kt)("h2",{id:"-contract-interaction-on-cosmwasm-with-celestia"},"\ud83c\udf1f Contract interaction on CosmWasm with Celestia"),(0,o.kt)("p",null,"In the previous steps, we have stored out contract's tx hash in an\nenvironment variable for later use."),(0,o.kt)("p",null,"Because of the longer time periods of submitting transactions via Rollkit\ndue to waiting on Celestia's data availability layer to confirm block inclusion,\nwe will need to query our tx hash directly to get information about it."),(0,o.kt)("h3",{id:"-contract-querying"},"\ud83d\udd0e Contract querying"),(0,o.kt)("p",null,"Let's start by querying our transaction hash for its code ID:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"CODE_ID=$(wasmd query tx --type=hash $TX_HASH --chain-id celeswasm --node http://127.0.0.1:26657 --output json | jq -r '.logs[0].events[-1].attributes[0].value')\necho $CODE_ID\n")),(0,o.kt)("p",null,"This will give us back the Code ID of the deployed contract."),(0,o.kt)("p",null,"In our case, since it's the first contract deployed on our local network,\nthe value is ",(0,o.kt)("inlineCode",{parentName:"p"},"1"),"."),(0,o.kt)("p",null,"Now, we can take a look at the contracts instantiated by this Code ID:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --node http://127.0.0.1:26657 --output json\n")),(0,o.kt)("p",null,"We get the following output:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-json"},'{"contracts":[],"pagination":{"next_key":null,"total":"0"}}\n')),(0,o.kt)("h3",{id:"-contract-instantiation"},"\ud83d\udcc3 Contract instantiation"),(0,o.kt)("p",null,"We start instantiating the contract by writing up the following ",(0,o.kt)("inlineCode",{parentName:"p"},"INIT")," message\nfor nameservice contract. Here, we are specifying that ",(0,o.kt)("inlineCode",{parentName:"p"},"purchase_price")," of a name\nis ",(0,o.kt)("inlineCode",{parentName:"p"},"100uwasm")," and ",(0,o.kt)("inlineCode",{parentName:"p"},"transfer_price")," is ",(0,o.kt)("inlineCode",{parentName:"p"},"999uwasm"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'INIT=\'{"purchase_price":{"amount":"100","denom":"uwasm"},"transfer_price":{"amount":"999","denom":"uwasm"}}\'\nwasmd tx wasm instantiate $CODE_ID "$INIT" --from celeswasm-key --keyring-backend test --label "name service" --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 -y --no-admin --node http://127.0.0.1:26657\n')),(0,o.kt)("h3",{id:"-contract-interaction"},"\ud83d\udcc4 Contract interaction"),(0,o.kt)("p",null,"Now that we instantiated it, we can interact further with the contract:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --output json --node http://127.0.0.1:26657\nCONTRACT=$(wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --output json --node http://127.0.0.1:26657 | jq -r '.contracts[-1]')\necho $CONTRACT\n\nwasmd query wasm contract --node http://127.0.0.1:26657 $CONTRACT --chain-id celeswasm\nwasmd query bank balances --node http://127.0.0.1:26657 $CONTRACT --chain-id celeswasm\n")),(0,o.kt)("p",null,"This allows us to see the contract address, contract details, and\nbank balances."),(0,o.kt)("p",null,"Your output will look similar to below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'{"contracts":["wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d"],"pagination":{"next_key":null,"total":"0"}}\nwasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d\naddress: wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d\ncontract_info:\n admin: ""\n code_id: "1"\n created: null\n creator: wasm1y9ceqvnsnm9xtcdmhrjvv4rslgwfzmrzky2c5z\n extension: null\n ibc_port_id: ""\n label: name service\nbalances: []\npagination:\n next_key: null\n total: "0"\n')),(0,o.kt)("p",null,"Now, let's register a name to the contract for our wallet address:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'REGISTER=\'{"register":{"name":"fred"}}\'\nwasmd tx wasm execute $CONTRACT "$REGISTER" --amount 100uwasm --from celeswasm-key --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 --node http://127.0.0.1:26657 --keyring-backend test -y\n')),(0,o.kt)("p",null,"Your output will look similar to below:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'DEIP --keyring-backend test -y\ngas estimate: 167533\ncode: 0\ncodespace: ""\ndata: ""\nevents: []\ngas_used: "0"\ngas_wanted: "0"\nheight: "0"\ninfo: ""\nlogs: []\nraw_log: \'[]\'\ntimestamp: ""\ntx: null\ntxhash: C147257485B72E7FFA5FDB943C94CE951A37817554339586FFD645AD2AA397C3\n')),(0,o.kt)("p",null,"If you try to register the same name again, you'll see an expected error:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"Error: rpc error: code = Unknown desc = rpc error: code = Unknown desc = failed to execute message; message index: 0: Name has been taken (name fred): execute wasm contract failed [CosmWasm/wasmd/x/wasm/keeper/keeper.go:364] With gas wanted: '0' and gas used: '123809' : unknown request\n")),(0,o.kt)("p",null,"Next, query the owner of the name record:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'NAME_QUERY=\'{"resolve_record": {"name": "fred"}}\'\nwasmd query wasm contract-state smart $CONTRACT "$NAME_QUERY" --chain-id celeswasm --node http://127.0.0.1:26657 --output json\n')),(0,o.kt)("p",null,"You'll see the owner's address in a JSON response:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},'{"data":{"address":"wasm1y9ceqvnsnm9xtcdmhrjvv4rslgwfzmrzky2c5z"}}\n')),(0,o.kt)("p",null,"With that, we have instantiated and interacted with the CosmWasm nameservice\nsmart contract using Celestia!"))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/feb3943e.7b2bdf60.js b/pr-preview/pr-192/assets/js/feb3943e.7b2bdf60.js deleted file mode 100644 index 98a736cf9..000000000 --- a/pr-preview/pr-192/assets/js/feb3943e.7b2bdf60.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[4500],{7629:e=>{e.exports=JSON.parse('{"title":"Beginner","slug":"/category/beginner","permalink":"/pr-preview/pr-192/docs/category/beginner","navigation":{"previous":{"title":"Tutorials","permalink":"/pr-preview/pr-192/docs/category/tutorials"},"next":{"title":"Building & deploying a rollup","permalink":"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup"}}}')}}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/main.b1788751.js b/pr-preview/pr-192/assets/js/main.b1788751.js deleted file mode 100644 index 848799245..000000000 --- a/pr-preview/pr-192/assets/js/main.b1788751.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.b1788751.js.LICENSE.txt */ -(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[179],{723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),l=n(6887);const s={"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,1223)),"@theme/BlogTagsListPage",1223],"0e384e19":[()=>n.e(9671).then(n.bind(n,9881)),"@site/docs/intro.md",9881],"14eb3368":[()=>Promise.all([n.e(532),n.e(9817)]).then(n.bind(n,4228)),"@theme/DocCategoryGeneratedIndexPage",4228],"17010a1c":[()=>n.e(7284).then(n.t.bind(n,2532,19)),"~blog/default/pr-preview-pr-192-blog-tags-rollkit-7b8-list.json",2532],17896441:[()=>Promise.all([n.e(532),n.e(7036),n.e(7918)]).then(n.bind(n,5154)),"@theme/DocItem",5154],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c091541":[()=>n.e(8271).then(n.t.bind(n,4469,19)),"/home/runner/work/docs/docs/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",4469],"1df93b7f":[()=>Promise.all([n.e(532),n.e(3237)]).then(n.bind(n,8391)),"@site/src/pages/index.tsx",8391],"21d57c30":[()=>n.e(6592).then(n.t.bind(n,9484,19)),"~blog/default/pr-preview-pr-192-blog-3e9.json",9484],"247783bb":[()=>n.e(9334).then(n.t.bind(n,3769,19)),"/home/runner/work/docs/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"2952c598":[()=>n.e(7087).then(n.bind(n,1843)),"@site/docs/tutorials/gm-world-frontend.md",1843],"2e006f0d":[()=>n.e(1392).then(n.bind(n,2453)),"@site/docs/tutorials/restart-rollkit-rollup.md",2453],"32f16e92":[()=>n.e(8757).then(n.bind(n,3481)),"@site/blog/2023-03-08-lets-roll.mdx?truncated=true",3481],"33efe628":[()=>n.e(6688).then(n.bind(n,2692)),"@site/blog/2023-02-21-introducing-rollkit.mdx",2692],"4650ee82":[()=>n.e(7238).then(n.t.bind(n,1007,19)),"~blog/default/pr-preview-pr-192-blog-tags-tags-2fc.json",1007],"4789b10c":[()=>n.e(3553).then(n.t.bind(n,247,19)),"~docs/default/category-pr-previewpr-192-docs-docs-category-advanced-88a.json",247],"48bdfc14":[()=>n.e(7819).then(n.t.bind(n,5409,19)),"~docs/default/category-pr-previewpr-192-docs-docs-category-tutorials-5d9.json",5409],"53f25740":[()=>Promise.all([n.e(532),n.e(9048)]).then(n.bind(n,651)),"@site/docs/tutorials/gm-world.md",651],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,6809)),"@generated/docusaurus.config",6809],"6875c492":[()=>Promise.all([n.e(532),n.e(7036),n.e(6048),n.e(8610)]).then(n.bind(n,1714)),"@theme/BlogTagsPostsPage",1714],"73f84a4a":[()=>n.e(9492).then(n.t.bind(n,9026,19)),"~blog/default/pr-preview-pr-192-blog-tags-celestia-c75-list.json",9026],"7aa79d9e":[()=>n.e(5331).then(n.bind(n,1420)),"@site/blog/2023-03-08-lets-roll.mdx",1420],"7d4011c1":[()=>n.e(2844).then(n.bind(n,8672)),"@site/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx?truncated=true",8672],"80930d5b":[()=>n.e(8347).then(n.t.bind(n,2561,19)),"~blog/default/pr-preview-pr-192-blog-archive-247.json",2561],"814f3328":[()=>n.e(2535).then(n.t.bind(n,5641,19)),"~blog/default/blog-post-list-prop-default.json",5641],"84d3f767":[()=>n.e(863).then(n.bind(n,1053)),"@site/blog/2023-02-21-introducing-rollkit.mdx?truncated=true",1053],"85430e88":[()=>n.e(9643).then(n.t.bind(n,3490,19)),"~blog/default/pr-preview-pr-192-blog-tags-rollkit-7b8.json",3490],"8f6681fc":[()=>n.e(5191).then(n.bind(n,4254)),"@site/docs/tutorials/ethermint.md",4254],"9064f397":[()=>n.e(5326).then(n.t.bind(n,8612,19)),"~blog/default/pr-preview-pr-192-blog-tags-celestia-c75.json",8612],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"9434eb16":[()=>n.e(8362).then(n.t.bind(n,4886,19)),"~blog/default/pr-preview-pr-192-blog-tags-bitcoin-3bf.json",4886],"94d5b9f3":[()=>n.e(3265).then(n.bind(n,740)),"@site/docs/tutorials/bitcoin.md",740],"9e4087bc":[()=>n.e(3608).then(n.bind(n,3169)),"@theme/BlogArchivePage",3169],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(7036),n.e(6048),n.e(3089)]).then(n.bind(n,46)),"@theme/BlogListPage",46],a7434565:[()=>n.e(7645).then(n.t.bind(n,5745,19)),"/home/runner/work/docs/docs/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",5745],b7833b35:[()=>n.e(7164).then(n.t.bind(n,5680,19)),"~blog/default/pr-preview-pr-192-blog-tags-bitcoin-3bf-list.json",5680],be631169:[()=>n.e(8235).then(n.bind(n,18)),"@site/docs/tutorials/recipe-book.md",18],c463304d:[()=>n.e(2193).then(n.bind(n,8793)),"@site/docs/rollkit-stack.md",8793],c7d6d209:[()=>n.e(8696).then(n.bind(n,449)),"@site/docs/tutorials/wordle.md",449],ccc49370:[()=>Promise.all([n.e(532),n.e(7036),n.e(6048),n.e(6103)]).then(n.bind(n,5203)),"@theme/BlogPostPage",5203],cd10b72d:[()=>n.e(6105).then(n.bind(n,1801)),"@site/docs/tutorials/building-and-deploying-a-rollup.md",1801],dbc9f6d7:[()=>n.e(1074).then(n.bind(n,4333)),"@site/docs/transaction-flow.md",4333],ddc2e5d7:[()=>n.e(8714).then(n.bind(n,1275)),"@site/blog/2023-03-5-sovereign-rollups-on-bitcoin-with-rollkit.mdx",1275],e8a90596:[()=>n.e(5986).then(n.t.bind(n,4885,19)),"~docs/default/category-pr-previewpr-192-docs-docs-category-intermediate-138.json",4885],ea3e41d5:[()=>Promise.all([n.e(532),n.e(5842)]).then(n.bind(n,8169)),"@site/docs/tutorials/cosmwasm.md",8169],feb3943e:[()=>n.e(4500).then(n.t.bind(n,7629,19)),"~docs/default/category-pr-previewpr-192-docs-docs-category-beginner-10f.json",7629]};function u(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var c=n(9670),d=n(226);function p(e,t){if("*"===e)return i()({loading:u,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=l[`${e}-${t}`],p={},f=[],m=[],g=(0,c.Z)(o);return Object.entries(g).forEach((e=>{let[t,n]=e;const r=s[n];r&&(p[t]=r[0],f.push(r[1]),m.push(r[2]))})),i().Map({loading:u,loader:p,modules:f,webpack:()=>m,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const l=n.split(".");l.slice(0,-1).forEach((e=>{o=o[e]})),o[l[l.length-1]]=a}));const l=i.__comp;delete i.__comp;const s=i.__context;return delete i.__context,r.createElement(d.z,{value:s},r.createElement(l,(0,a.Z)({},i,n)))}})}const f=[{path:"/pr-preview/pr-192/blog/",component:p("/pr-preview/pr-192/blog/","65f"),exact:!0},{path:"/pr-preview/pr-192/blog/archive/",component:p("/pr-preview/pr-192/blog/archive/","e68"),exact:!0},{path:"/pr-preview/pr-192/blog/introducing-rollkit/",component:p("/pr-preview/pr-192/blog/introducing-rollkit/","aa9"),exact:!0},{path:"/pr-preview/pr-192/blog/lets-roll-community-call/",component:p("/pr-preview/pr-192/blog/lets-roll-community-call/","7ab"),exact:!0},{path:"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/",component:p("/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/","b75"),exact:!0},{path:"/pr-preview/pr-192/blog/tags/",component:p("/pr-preview/pr-192/blog/tags/","b14"),exact:!0},{path:"/pr-preview/pr-192/blog/tags/bitcoin/",component:p("/pr-preview/pr-192/blog/tags/bitcoin/","fd3"),exact:!0},{path:"/pr-preview/pr-192/blog/tags/celestia/",component:p("/pr-preview/pr-192/blog/tags/celestia/","038"),exact:!0},{path:"/pr-preview/pr-192/blog/tags/rollkit/",component:p("/pr-preview/pr-192/blog/tags/rollkit/","0e4"),exact:!0},{path:"/pr-preview/pr-192/docs/",component:p("/pr-preview/pr-192/docs/","bff"),routes:[{path:"/pr-preview/pr-192/docs/category/advanced/",component:p("/pr-preview/pr-192/docs/category/advanced/","b1f"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/category/beginner/",component:p("/pr-preview/pr-192/docs/category/beginner/","e28"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/category/intermediate/",component:p("/pr-preview/pr-192/docs/category/intermediate/","27f"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/category/tutorials/",component:p("/pr-preview/pr-192/docs/category/tutorials/","387"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/intro/",component:p("/pr-preview/pr-192/docs/intro/","1ef"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/rollkit-stack/",component:p("/pr-preview/pr-192/docs/rollkit-stack/","8e3"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/transaction-flow/",component:p("/pr-preview/pr-192/docs/transaction-flow/","957"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/bitcoin/",component:p("/pr-preview/pr-192/docs/tutorials/bitcoin/","ce8"),exact:!0},{path:"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/",component:p("/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/","59b"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/cosmwasm/",component:p("/pr-preview/pr-192/docs/tutorials/cosmwasm/","67c"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/ethermint/",component:p("/pr-preview/pr-192/docs/tutorials/ethermint/","899"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/gm-world-frontend/",component:p("/pr-preview/pr-192/docs/tutorials/gm-world-frontend/","6ce"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/gm-world/",component:p("/pr-preview/pr-192/docs/tutorials/gm-world/","58f"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/recipe-book/",component:p("/pr-preview/pr-192/docs/tutorials/recipe-book/","591"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/",component:p("/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/","b0a"),exact:!0,sidebar:"docs"},{path:"/pr-preview/pr-192/docs/tutorials/wordle/",component:p("/pr-preview/pr-192/docs/tutorials/wordle/","2fa"),exact:!0,sidebar:"docs"}]},{path:"/pr-preview/pr-192/",component:p("/pr-preview/pr-192/","289"),exact:!0},{path:"*",component:p("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),l=n(412);const s=[n(2497),n(3310),n(8320),n(2295)];var u=n(723),c=n(6550),d=n(8790);function p(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var f=n(7462),m=n(5742),g=n(2263),h=n(4996),v=n(6668),b=n(1944),y=n(4711),w=n(9727),k=n(3320),E=n(197);function S(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,g.Z)(),n=(0,y.l)();return r.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function x(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,g.Z)(),a=function(){const{siteConfig:{url:e}}=(0,g.Z)(),{pathname:t}=(0,c.TH)();return e+(0,h.Z)(t)}(),o=t?`${n}${t}`:a;return r.createElement(m.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function C(){const{i18n:{currentLocale:e}}=(0,g.Z)(),{metadata:t,image:n}=(0,v.L)();return r.createElement(r.Fragment,null,r.createElement(m.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(b.d,{image:n}),r.createElement(x,null),r.createElement(S,null),r.createElement(E.Z,{tag:k.HX,locale:e}),r.createElement(m.Z,null,t.map(((e,t)=>r.createElement("meta",(0,f.Z)({key:t},e))))))}const _=new Map;function T(e){if(_.has(e.pathname))return{...e,pathname:_.get(e.pathname)};if((0,d.f)(u.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return _.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return _.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),L=n(8940);function R(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];const a=s.map((t=>(t.default?.[e]??t[e])?.(...n)));return()=>a.forEach((e=>e?.()))}const P=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(a&&function(e){const{hash:t}=e;if(t){const e=decodeURIComponent(t.substring(1));document.getElementById(e)?.scrollIntoView()}else window.scrollTo(0,0)}(n),R("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function N(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(u.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class O extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=l.Z.canUseDOM?R("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=R("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(P,{previousLocation:this.previousLocation,location:t},r.createElement(c.AW,{location:t,render:()=>e}))}}const I=O,D="docusaurus-base-url-issue-banner-container",M="docusaurus-base-url-issue-banner-suggestion-container",F="__DOCUSAURUS_INSERT_BASEURL_BANNER";function j(e){return`\nwindow['${F}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${F}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${D}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseurl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${M}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n var suggestionContainer = document.getElementById('${M}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function B(){const{siteConfig:{baseUrl:e}}=(0,g.Z)();return(0,r.useLayoutEffect)((()=>{window[F]=!1}),[]),r.createElement(r.Fragment,null,!l.Z.canUseDOM&&r.createElement(m.Z,null,r.createElement("script",null,j(e))),r.createElement("div",{id:D}))}function z(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,g.Z)(),{pathname:n}=(0,c.TH)();return t&&n===e?r.createElement(B,null):null}function U(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,g.Z)(),i=(0,h.Z)(e),{htmlLang:l,direction:s}=o[a];return r.createElement(m.Z,null,r.createElement("html",{lang:l,dir:s}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var $=n(4763);function q(){const e=(0,d.H)(u.Z),t=(0,c.TH)();return r.createElement($.Z,null,r.createElement(L.M,null,r.createElement(A.t,null,r.createElement(p,null,r.createElement(U,null),r.createElement(C,null),r.createElement(z,null),r.createElement(I,{location:T(t)},e)))))}var G=n(6887);const H=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();(document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode)?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Z=n(9670);const V=new Set,W=new Set,Y=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,K={prefetch(e){if(!(e=>!Y()&&!W.has(e)&&!V.has(e))(e))return!1;V.add(e);const t=(0,d.f)(u.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(G).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Z.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?H(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!Y()&&!W.has(e))(e)&&(W.add(e),N(e))},Q=Object.freeze(K);if(l.Z.canUseDOM){window.docusaurus=Q;const e=a.hydrate;N(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(q,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>c,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/pr-preview/pr-192/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/pr-preview/pr-192/docs","mainDocId":"intro","docs":[{"id":"intro","path":"/pr-preview/pr-192/docs/intro","sidebar":"docs"},{"id":"rollkit-stack","path":"/pr-preview/pr-192/docs/rollkit-stack","sidebar":"docs"},{"id":"transaction-flow","path":"/pr-preview/pr-192/docs/transaction-flow","sidebar":"docs"},{"id":"tutorials/bitcoin","path":"/pr-preview/pr-192/docs/tutorials/bitcoin"},{"id":"tutorials/building-and-deploying-a-rollup","path":"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup","sidebar":"docs"},{"id":"tutorials/cosmwasm","path":"/pr-preview/pr-192/docs/tutorials/cosmwasm","sidebar":"docs"},{"id":"tutorials/ethermint","path":"/pr-preview/pr-192/docs/tutorials/ethermint","sidebar":"docs"},{"id":"tutorials/gm-world","path":"/pr-preview/pr-192/docs/tutorials/gm-world","sidebar":"docs"},{"id":"tutorials/gm-world-frontend","path":"/pr-preview/pr-192/docs/tutorials/gm-world-frontend","sidebar":"docs"},{"id":"tutorials/recipe-book","path":"/pr-preview/pr-192/docs/tutorials/recipe-book","sidebar":"docs"},{"id":"tutorials/restart-rollkit-rollup","path":"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup","sidebar":"docs"},{"id":"tutorials/wordle","path":"/pr-preview/pr-192/docs/tutorials/wordle","sidebar":"docs"},{"id":"/category/tutorials","path":"/pr-preview/pr-192/docs/category/tutorials","sidebar":"docs"},{"id":"/category/beginner","path":"/pr-preview/pr-192/docs/category/beginner","sidebar":"docs"},{"id":"/category/intermediate","path":"/pr-preview/pr-192/docs/category/intermediate","sidebar":"docs"},{"id":"/category/advanced","path":"/pr-preview/pr-192/docs/category/advanced","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/pr-preview/pr-192/docs/intro","label":"Intro"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var l=n(7529);const s=JSON.parse('{"docusaurusVersion":"2.2.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.2.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.2.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.2.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.2.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.2.0"}}}'),u={siteConfig:a.default,siteMetadata:s,globalData:o,i18n:i,codeTranslations:l},c=r.createContext(u);function d(e){let{children:t}=e;return r.createElement(c.Provider,{value:u},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7294),a=n(412),o=n(5742),i=n(7676);function l(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",height:"50vh",width:"100%",fontSize:"20px"}},r.createElement("h1",null,"This page crashed."),r.createElement("p",null,t.message),r.createElement("button",{type:"button",onClick:n},"Try again"))}function s(e){let{error:t,tryAgain:n}=e;return r.createElement(c,{fallback:()=>r.createElement(l,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(i.Z,null,r.createElement(l,{error:t,tryAgain:n})))}const u=e=>r.createElement(s,e);class c extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??u)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),l=n(2263),s=n(3919),u=n(412);const c=a.createContext({collectLink:()=>{}});var d=n(4996);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:v=!0,...b}=e;const{siteConfig:{trailingSlash:y,baseUrl:w}}=(0,l.Z)(),{withBaseUrl:k}=(0,d.C)(),E=(0,a.useContext)(c),S=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>S.current));const x=p||f;const C=(0,s.Z)(x),_=x?.replace("pathname://","");let T=void 0!==_?(A=_,v&&(e=>e.startsWith("/"))(A)?k(A):A):void 0;var A;T&&C&&(T=(0,i.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:w}));const L=(0,a.useRef)(!1),R=n?o.OL:o.rU,P=u.Z.canUseIntersectionObserver,N=(0,a.useRef)(),O=()=>{L.current||null==T||(window.docusaurus.preload(T),L.current=!0)};(0,a.useEffect)((()=>(!P&&C&&null!=T&&window.docusaurus.prefetch(T),()=>{P&&N.current&&N.current.disconnect()})),[N,T,P,C]);const I=T?.startsWith("#")??!1,D=!T||!C||I;return D||h||E.collectLink(T),D?a.createElement("a",(0,r.Z)({ref:S,href:T},x&&!C&&{target:"_blank",rel:"noopener noreferrer"},b)):a.createElement(R,(0,r.Z)({},b,{onMouseEnter:O,onTouchStart:O,innerRef:e=>{S.current=e,P&&e&&C&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),N.current.observe(e))},to:T},n&&{isActive:g,activeClassName:m}))}const f=a.forwardRef(p)},1875:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const r=()=>null},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>s,I:()=>l});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function s(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const l=i({message:t,id:n});return r.createElement(r.Fragment,null,a(l,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>o,Z:()=>i});var r=n(2263),a=n(3919);function o(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)();return{withBaseUrl:(n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a.b)(n))return n;if(o)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const l=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+l:l}(t,e,n,r)}}function i(e,t){void 0===t&&(t={});const{withBaseUrl:n}=o();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[a,o]=n;const i=r?`${r}.${a}`:a;var l;"object"==typeof(l=o)&&l&&Object.keys(l).length>0?e(o,i):t[i]=o}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>g,gA:()=>p,_r:()=>c,Jo:()=>h,zh:()=>d,yW:()=>m,gB:()=>f});var r=n(6550),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const l=e=>e.versions.find((e=>e.isLast));function s(e,t){const n=function(e,t){const n=l(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const u={},c=()=>i("docusaurus-plugin-content-docs")??u,d=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e)?.[t];if(!r&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return r}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=c(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function f(e){return d(e).versions}function m(e){const t=d(e);return l(t)}function g(e){const t=d(e),{pathname:n}=(0,r.TH)();return s(t,n)}function h(e){const t=d(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=l(e);return{latestDocSuggestion:s(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a="iconExternalLink_nPIU";function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},7676:(e,t,n)=>{"use strict";n.d(t,{Z:()=>ut});var r=n(7294),a=n(6010),o=n(4763),i=n(1944),l=n(7462),s=n(6550),u=n(5999),c=n(5936);const d="docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,u.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:a}=f();return r.createElement("div",{ref:n,role:"region","aria-label":m},r.createElement("a",(0,l.Z)({},e,{href:`#${d}`,onClick:a}),t))}var h=n(5281),v=n(9727);const b="skipToContent_fXgn";function y(){return r.createElement(g,{className:b})}var w=n(6668),k=n(9689);function E(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...s}=e;return r.createElement("svg",(0,l.Z)({viewBox:"0 0 15 15",width:t,height:n},s),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const S="closeButton_CVFx";function x(e){return r.createElement("button",(0,l.Z)({type:"button","aria-label":(0,u.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",S,e.className)}),r.createElement(E,{width:14,height:14,strokeWidth:3.1}))}const C="content_knG7";function _(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return r.createElement("div",(0,l.Z)({},e,{className:(0,a.Z)(C,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T="announcementBar_mb4j",A="announcementBarPlaceholder_vyr4",L="announcementBarClose_gvF7",R="announcementBarContent_xLdY";function P(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,k.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:A}),r.createElement(_,{className:R}),i&&r.createElement(x,{onClick:n,className:L}))}var N=n(2961),O=n(2466);var I=n(902),D=n(3102);const M=r.createContext(null);function F(e){let{children:t}=e;const n=function(){const e=(0,N.e)(),t=(0,D.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,I.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(M.Provider,{value:n},t)}function j(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function B(){const e=(0,r.useContext)(M);if(!e)throw new I.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,D.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:j(o)})),[a,o,t])}function z(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=B();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var U=n(2949),$=n(2389);function q(e){return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function G(e){return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const H={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function Z(e){let{className:t,value:n,onChange:o}=e;const i=(0,$.Z)(),l=(0,u.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===n?(0,u.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,u.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)(H.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",H.toggleButton,!i&&H.toggleButtonDisabled),type:"button",onClick:()=>o("dark"===n?"light":"dark"),disabled:!i,title:l,"aria-label":l,"aria-live":"polite"},r.createElement(q,{className:(0,a.Z)(H.toggleIcon,H.lightToggleIcon)}),r.createElement(G,{className:(0,a.Z)(H.toggleIcon,H.darkToggleIcon)})))}const V=r.memo(Z);function W(e){let{className:t}=e;const n=(0,w.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:o}=(0,U.I)();return n?null:r.createElement(V,{className:t,value:a,onChange:o})}var Y=n(1327);function K(){return r.createElement(Y.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,N.e)();return r.createElement("button",{type:"button","aria-label":(0,u.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(E,{color:"var(--ifm-color-emphasis-600)"}))}function X(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(K,null),r.createElement(W,{className:"margin-right--md"}),r.createElement(Q,null))}var J=n(9960),ee=n(4996),te=n(3919);function ne(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var re=n(9471);function ae(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:s,isDropdownLink:u,prependBaseUrlToHref:c,...d}=e;const p=(0,ee.Z)(a),f=(0,ee.Z)(t),m=(0,ee.Z)(o,{forcePrependBaseUrl:!0}),g=i&&o&&!(0,te.Z)(o),h=s?{dangerouslySetInnerHTML:{__html:s}}:{children:r.createElement(r.Fragment,null,i,g&&r.createElement(re.Z,u&&{width:12,height:12}))};return o?r.createElement(J.Z,(0,l.Z)({href:c?m:o},d,h)):r.createElement(J.Z,(0,l.Z)({to:p,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?ne(n,t.pathname):t.pathname.startsWith(f)},d,h))}function oe(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(ae,(0,l.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function ie(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(ae,(0,l.Z)({className:(0,a.Z)("menu__link",t)},o)))}function le(e){let{mobile:t=!1,position:n,...a}=e;const o=t?ie:oe;return r.createElement(o,(0,l.Z)({},a,{activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var se=n(6043),ue=n(8596),ce=n(2263);function de(e,t){return e.some((e=>function(e,t){return!!(0,ue.Mg)(e.to,t)||!!ne(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function pe(e){let{items:t,position:n,className:o,onClick:i,...s}=e;const u=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{u.current&&!u.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e)}}),[u]),r.createElement("div",{ref:u,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c})},r.createElement(ae,(0,l.Z)({"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,a.Z)("navbar__link",o)},s,{onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))}}),s.children??s.label),r.createElement("ul",{className:"dropdown__menu"},t.map(((e,n)=>r.createElement(_e,(0,l.Z)({isDropdownItem:!0,onKeyDown:e=>{if(n===t.length-1&&"Tab"===e.key){e.preventDefault(),d(!1);const t=u.current.nextElementSibling;if(t){(t instanceof HTMLAnchorElement?t:t.querySelector("a")).focus()}}},activeClassName:"dropdown__link--active"},e,{key:n}))))))}function fe(e){let{items:t,className:n,position:o,onClick:i,...u}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,ce.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=de(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,se.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":p})},r.createElement(ae,(0,l.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},u,{onClick:e=>{e.preventDefault(),f()}}),u.children??u.label),r.createElement(se.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p},t.map(((e,t)=>r.createElement(_e,(0,l.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function me(e){let{mobile:t=!1,...n}=e;const a=t?fe:pe;return r.createElement(a,n)}var ge=n(4711);function he(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,l.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const ve="iconLanguage_nlXk";var be=n(1875);const ye="searchBox_ZlJk";function we(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,ye)},t)}var ke=n(143),Ee=n(3438);var Se=n(373);const xe=e=>e.docs.find((t=>t.id===e.mainDocId));const Ce={default:le,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,ce.Z)(),p=(0,ge.l)(),{search:f,hash:m}=(0,s.TH)(),g=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],h=t?(0,u.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(me,(0,l.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(he,{className:ve}),h),items:g}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(we,{className:n},r.createElement(be.Z,null))},dropdown:me,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const l=i?"li":"div";return r.createElement(l,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ke.Iw)(a),s=(0,Ee.vY)(t,a);return null===s?null:r.createElement(le,(0,l.Z)({exact:!0},o,{isActive:()=>i?.path===s.path||!!i?.sidebar&&i.sidebar===s.sidebar,label:n??s.id,to:s.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,ke.Iw)(a),s=(0,Ee.oz)(t,a).link;if(!s)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return r.createElement(le,(0,l.Z)({exact:!0},o,{isActive:()=>i?.sidebar===t,label:n??s.label,to:s.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,Ee.lO)(a)[0],s=t??i.label,u=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(le,(0,l.Z)({},o,{label:s,to:u}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...c}=e;const{search:d,hash:p}=(0,s.TH)(),f=(0,ke.Iw)(n),m=(0,ke.gB)(n),{savePreferredVersionName:g}=(0,Se.J)(n),h=[...o,...m.map((e=>{const t=f.alternateDocVersions[e.name]??xe(e);return{label:e.label,to:`${t.path}${d}${p}`,isActive:()=>e===f.activeVersion,onClick:()=>g(e.name)}})),...i],v=(0,Ee.lO)(n)[0],b=t&&h.length>1?(0,u.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):v.label,y=t&&h.length>1?void 0:xe(v).path;return h.length<=1?r.createElement(le,(0,l.Z)({},c,{mobile:t,label:b,to:y,isActive:a?()=>!1:void 0})):r.createElement(me,(0,l.Z)({},c,{mobile:t,label:b,to:y,items:h,isActive:a?()=>!1:void 0}))}};function _e(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ce[a];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(o,n)}function Te(){const e=(0,N.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(_e,(0,l.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ae(e){return r.createElement("button",(0,l.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(u.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Le(){const e=0===(0,w.L)().navbar.items.length,t=B();return r.createElement(r.Fragment,null,!e&&r.createElement(Ae,{onClick:()=>t.hide()}),t.content)}function Re(){const e=(0,N.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(z,{header:r.createElement(X,null),primaryMenu:r.createElement(Te,null),secondaryMenu:r.createElement(Le,null)}):null}const Pe="navbarHideable_m1mJ",Ne="navbarHidden_jGov";function Oe(e){return r.createElement("div",(0,l.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function Ie(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,N.e)(),{navbarRef:l,isNavbarVisible:s}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,O.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i<o.current)return void n(!0);if(a.current)return void(a.current=!1);const l=r?.scrollY,s=document.documentElement.scrollHeight-o.current,u=window.innerHeight;l&&i>=l?n(!1):i+u<s&&n(!0)})),(0,c.S)((t=>{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:l,className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Pe,!s&&Ne],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Oe,{onClick:i.toggle}),r.createElement(Re,null))}function De(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,l.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function Me(){const{toggle:e,shown:t}=(0,N.e)();return r.createElement("button",{onClick:e,"aria-label":(0,u.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(De,null))}const Fe="colorModeToggle_DEke";function je(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(_e,(0,l.Z)({},e,{key:t})))))}function Be(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function ze(){const e=(0,N.e)(),t=(0,w.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??"right")}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(Be,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(Me,null),r.createElement(K,null),r.createElement(je,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(je,{items:a}),r.createElement(W,{className:Fe}),!o&&r.createElement(we,null,r.createElement(be.Z,null)))})}function Ue(){return r.createElement(Ie,null,r.createElement(ze,null))}function $e(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...s}=t,u=(0,ee.Z)(n),c=(0,ee.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(J.Z,(0,l.Z)({className:"footer__link-item"},a?{href:i?c:a}:{to:u},s),o,a&&!(0,te.Z)(a)&&r.createElement(re.Z,null))}function qe(e){let{item:t}=e;return t.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement("li",{key:t.href??t.to,className:"footer__item"},r.createElement($e,{item:t}))}function Ge(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(qe,{key:t,item:e})))))}function He(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(Ge,{key:t,column:e}))))}function Ze(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function Ve(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement($e,{item:t})}function We(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(Ve,{item:e}),t.length!==n+1&&r.createElement(Ze,null))))))}function Ye(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(He,{columns:t}):r.createElement(We,{links:t})}var Ke=n(941);const Qe="footerLogoLink_BH7S";function Xe(e){let{logo:t}=e;const{withBaseUrl:n}=(0,ee.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(Ke.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function Je(e){let{logo:t}=e;return t.href?r.createElement(J.Z,{href:t.href,className:Qe,target:t.target},r.createElement(Xe,{logo:t})):r.createElement(Xe,{logo:t})}function et(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function tt(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--center"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function nt(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(tt,{style:o,links:n&&n.length>0&&r.createElement(Ye,{links:n}),logo:a&&r.createElement(Je,{logo:a}),copyright:t&&r.createElement(et,{copyright:t})})}const rt=r.memo(nt);var at=n(7094);const ot=(0,I.Qc)([U.S,k.pl,at.z,O.OC,Se.L5,i.VC,function(e){let{children:t}=e;return r.createElement(D.n2,null,r.createElement(N.M,null,r.createElement(F,null,t)))}]);function it(e){let{children:t}=e;return r.createElement(ot,null,t)}function lt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(u.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("p",null,t.message),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},r.createElement(u.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again when the page crashed"},"Try again"))))))}const st="mainWrapper_z2l0";function ut(e){const{children:t,noFooter:n,wrapperClassName:l,title:s,description:u}=e;return(0,v.t)(),r.createElement(it,null,r.createElement(i.d,{title:s,description:u}),r.createElement(y,null),r.createElement(P,null),r.createElement(Ue,null),r.createElement("div",{id:d,className:(0,a.Z)(h.k.wrapper.main,st,l)},r.createElement(o.Z,{fallback:e=>r.createElement(lt,e)},t)),!n&&r.createElement(rt,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),l=n(2263),s=n(6668),u=n(941);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},l=a.createElement(u.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},l):l}function d(e){const{siteConfig:{title:t}}=(0,l.Z)(),{navbar:{title:n,logo:u}}=(0,s.L)(),{imageClassName:d,titleClassName:p,...f}=e,m=(0,i.Z)(u?.href||"/"),g=n?"":t,h=u?.alt??g;return a.createElement(o.Z,(0,r.Z)({to:m},f,u?.target&&{target:u.target}),u&&a.createElement(c,{logo:u,alt:h,imageClassName:d}),null!=n&&a.createElement("b",{className:p},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7462),a=n(7294),o=n(6010),i=n(2389),l=n(2949);const s={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function u(e){const t=(0,i.Z)(),{colorMode:n}=(0,l.I)(),{sources:u,className:c,alt:d,...p}=e,f=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,f.map((e=>a.createElement("img",(0,r.Z)({key:e,src:u[e],alt:d,className:(0,o.Z)(s.themedImage,s[`themedImage--${e}`],c)},p)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>i,z:()=>m});var r=n(7462),a=n(7294),o=n(412);function i(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const l={display:"none",overflow:"hidden",height:"0px"},s={display:"block",overflow:"visible",height:"auto"};function u(e,t){const n=t?l:s;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function c(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=r?.duration??function(e){const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??"ease-in-out"}`,height:`${t}px`}}function i(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return u(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(i(),requestAnimationFrame((()=>{e.style.height=l.height,e.style.overflow=l.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{i()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function d(e){if(!o.Z.canUseDOM)return e?l:s}function p(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:l,disableSSRStyle:s}=e;const p=(0,a.useRef)(null);return c({collapsibleRef:p,collapsed:n,animation:o}),a.createElement(t,{ref:p,style:s?void 0:d(n),onTransitionEnd:e=>{"height"===e.propertyName&&(u(p.current,n),i?.(n))},className:l},r)}function f(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[l,s]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&s(t)}),[o,t]),o?a.createElement(p,(0,r.Z)({},n,{collapsed:l})):null}function m(e){let{lazy:t,...n}=e;const r=t?f:p;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>f});var r=n(7294),a=n(2389),o=n(12),i=n(902),l=n(6668);const s=(0,o.W)("docusaurus.announcement.dismiss"),u=(0,o.W)("docusaurus.announcement.id"),c=()=>"true"===s.get(),d=e=>s.set(String(e)),p=r.createContext(null);function f(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,l.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&c()));(0,r.useEffect)((()=>{o(c())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&d(!1),!r&&c()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(p.Provider,{value:n},t)}function m(){const e=(0,r.useContext)(p);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>h,S:()=>g});var r=n(7294),a=n(412),o=n(902),i=n(12),l=n(6668);const s=r.createContext(void 0),u="theme",c=(0,i.W)(u),d="light",p="dark",f=e=>e===p?p:d;function m(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,l.L)(),[o,i]=(0,r.useState)((e=>a.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e))(e));(0,r.useEffect)((()=>{t&&c.del()}),[t]);const s=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(i(t),a&&(e=>{c.set(f(e))})(t)):(i(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p:d:e),c.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=c.get();null!==t&&s(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,s]);const m=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||m.current?m.current=window.matchMedia("print").matches:s(null)};return e.addListener(r),()=>e.removeListener(r)}),[s,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:s,get isDarkTheme(){return o===p},setLightTheme(){s(d)},setDarkTheme(){s(p)}})),[o,s])}function g(e){let{children:t}=e;const n=m();return r.createElement(s.Provider,{value:n},t)}function h(){const e=(0,r.useContext)(s);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>y,L5:()=>v});var r=n(7294),a=n(143),o=n(9935),i=n(6668),l=n(3438),s=n(902),u=n(12);const c=e=>`docs-preferred-version-${e}`,d=(e,t,n)=>{(0,u.W)(c(e),{persistence:t}).set(n)},p=(e,t)=>(0,u.W)(c(e),{persistence:t}).get(),f=(e,t)=>{(0,u.W)(c(e),{persistence:t}).del()};const m=r.createContext(null);function g(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,l]=(0,r.useState)((()=>(e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}]))))(n)));(0,r.useEffect)((()=>{l(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=p(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(f(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d(e,t,n),l((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function h(e){let{children:t}=e;const n=g();return r.createElement(m.Provider,{value:n},t)}function v(e){let{children:t}=e;return l.cE?r.createElement(h,null,t):r.createElement(r.Fragment,null,t)}function b(){const e=(0,r.useContext)(m);if(!e)throw new s.i6("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=b(),{preferredVersionName:l}=n[e];return{preferredVersion:t.versions.find((e=>e.name===l))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>s,b:()=>l});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function l(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function s(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t,version:n}=e;return r.createElement(o.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(o);if(null===e)throw new a.i6("DocsVersionProvider");return e}},2961:(e,t,n)=>{"use strict";n.d(t,{M:()=>p,e:()=>f});var r=n(7294),a=n(3102),o=n(7524),i=n(6550),l=n(902);function s(e){!function(e){const t=(0,i.k6)(),n=(0,l.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var u=n(6668);const c=r.createContext(void 0);function d(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,u.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[i,l]=(0,r.useState)(!1);s((()=>{if(i)return l(!1),!1}));const c=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:c,shown:i})),[e,n,c,i])}function p(e){let{children:t}=e;const n=d();return r.createElement(c.Provider,{value:n},t)}function f(){const e=r.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>l,Zo:()=>s,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function l(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function s(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,l]=i,s=(0,a.Ql)(n);return(0,r.useEffect)((()=>{l({component:t,props:s})}),[l,t,s]),(0,r.useEffect)((()=>()=>l({component:null,props:null})),[l]),null}},7094:(e,t,n)=>{"use strict";n.d(t,{U:()=>u,z:()=>s});var r=n(7294),a=n(12),o=n(902);const i="docusaurus.tab.",l=r.createContext(void 0);function s(e){let{children:t}=e;const n=function(){const[e,t]=(0,r.useState)({}),n=(0,r.useCallback)(((e,t)=>{(0,a.W)(`${i}${e}`).set(t)}),[]);(0,r.useEffect)((()=>{try{const e={};(0,a._)().forEach((t=>{if(t.startsWith(i)){const n=t.substring(i.length);e[n]=(0,a.W)(t).get()}})),t(e)}catch(e){console.error(e)}}),[]);const o=(0,r.useCallback)(((e,r)=>{t((t=>({...t,[e]:r}))),n(e,r)}),[n]);return(0,r.useMemo)((()=>({tabGroupChoices:e,setTabGroupChoices:o})),[e,o])}();return r.createElement(l.Provider,{value:n},t)}function u(){const e=(0,r.useContext)(l);if(null==e)throw new o.i6("TabGroupChoiceProvider");return e}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>u});var r=n(7294),a=n(412);const o="desktop",i="mobile",l="ssr";function s(){return a.Z.canUseDOM?window.innerWidth>996?o:i:l}function u(){const[e,t]=(0,r.useState)((()=>s()));return(0,r.useEffect)((()=>{function e(){t(s())}return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(undefined)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},3438:(e,t,n)=>{"use strict";n.d(t,{MN:()=>x,Wl:()=>m,_F:()=>v,cE:()=>p,hI:()=>S,jA:()=>g,lO:()=>w,oz:()=>k,s1:()=>y,vY:()=>E,xz:()=>f});var r=n(7294),a=n(6550),o=n(8790),i=n(143),l=n(373),s=n(4477),u=n(1116),c=n(7392),d=n(8596);const p=!!i._r;function f(e){const t=(0,s.E)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function m(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=m(t);if(e)return e}}}function g(){const{pathname:e}=(0,a.TH)(),t=(0,u.V)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=b({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const h=(e,t)=>void 0!==e&&(0,d.Mg)(e,t);function v(e,t){return"link"===e.type?h(e.href,t):"category"===e.type&&(h(e.href,t)||((e,t)=>e.some((e=>v(e,t))))(e.items,t))}function b(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function y(){const e=(0,u.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?b({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,l.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>(0,c.j)([t,n,a].filter(Boolean))),[t,n,a])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\n Available sidebar ids are:\n - ${Object.keys(t).join("\n- ")}`);return r[1]}),[e,n])}function E(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`DocNavbarItem: couldn't find any doc with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,c.j)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function S(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,l=i.find((e=>(0,a.LX)(r.pathname,e)));if(!l)return null;const s=l.sidebar,u=s?n.docsSidebars[s]:void 0;return{docElement:(0,o.H)(i),sidebarName:s,sidebarItems:u}}function x(e){return e.filter((e=>"category"!==e.type||!!m(e)))}},7392:(e,t,n)=>{"use strict";function r(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,r)=>e.findIndex((e=>t(e,n)))!==r))}function a(e){return Array.from(new Set(e))}n.d(t,{j:()=>a,l:()=>r})},1944:(e,t,n)=>{"use strict";n.d(t,{FG:()=>p,d:()=>c,VC:()=>f});var r=n(7294),a=n(6010),o=n(5742),i=n(226);function l(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var s=n(4996),u=n(2263);function c(e){let{title:t,description:n,keywords:a,image:i,children:l}=e;const c=function(e){const{siteConfig:t}=(0,u.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,s.C)(),p=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,c),t&&r.createElement("meta",{property:"og:title",content:c}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),p&&r.createElement("meta",{property:"og:image",content:p}),p&&r.createElement("meta",{name:"twitter:image",content:p}),l)}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),l=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:l},r.createElement(o.Z,null,r.createElement("html",{className:l})),n)}function f(e){let{children:t}=e;const n=l(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(p,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>u,Ql:()=>s,i6:()=>l,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function s(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>l});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function l(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>s,RF:()=>d,o5:()=>p});var r=n(7294),a=n(412),o=n(2389),i=n(902);const l=r.createContext(void 0);function s(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(l.Provider,{value:n},t)}function u(){const e=(0,r.useContext)(l);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const c=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),a=(0,r.useRef)(c()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=c();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function p(){const e=u(),t=function(){const e=(0,r.useRef)({elem:null,top:0}),t=(0,r.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,r.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const r=t.getBoundingClientRect().top-n;return r&&window.scrollBy({left:0,top:r}),e.current={elem:null,top:0},{restored:0!==r}}),[]);return(0,r.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,r.useRef)(void 0),a=(0,r.useCallback)((r=>{t.save(r),e.disableScrollEvents(),n.current=()=>{const{restored:r}=t.restore();if(n.current=void 0,r){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,r.useLayoutEffect)((()=>{n.current?.()})),{blockElementScrollPositionUntilNextRender:a}}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&a<e)&&(t=requestAnimationFrame(r),window.scrollTo(0,Math.floor(.85*(a-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>r,os:()=>a});n(2263);const r="default";function a(e,t){return`docs-${e}-${t}`}},12:(e,t,n)=>{"use strict";n.d(t,{W:()=>l,_:()=>s});const r="localStorage";function a(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,o||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),o=!0),null}var t}let o=!1;const i={get:()=>null,set:()=>{},del:()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t}}(e);const n=a(t?.persistence);return null===n?i:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{n.setItem(e,t)}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{n.removeItem(e)}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}}}}function s(e){void 0===e&&(e=r);const t=a(e);if(!t)return[];const n=[];for(let r=0;r<t.length;r+=1){const e=t.key(r);null!==e&&n.push(e)}return n}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var r=n(2263),a=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,r.Z)(),{pathname:i}=(0,a.TH)(),l=o===n?e:e.replace(`/${o}/`,"/"),s=i.replace(e,"");return{createUrl:function(e){let{locale:r,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===n?`${l}`:`${l}${e}/`}(r)}${s}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="post-content";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}})},6010:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(n=r(e[t]))&&(a&&(a+=" "),a+=n);else for(t in e)e[t]&&(a&&(a+=" "),a+=t);return a}n.d(t,{Z:()=>a});const a=function(){for(var e,t,n=0,a="";n<arguments.length;)(e=arguments[n++])&&(t=r(e))&&(a&&(a+=" "),a+=t);return a}},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>w,q_:()=>_,ob:()=>f,PP:()=>A,Ep:()=>p});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r<a;n+=1,r+=1)e[n]=e[r];e.pop()}const i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],l=e&&a(e),s=t&&a(t),u=l||s;if(e&&a(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var c=i[i.length-1];n="."===c||".."===c||""===c}else n=!1;for(var d=0,p=i.length;p>=0;p--){var f=i[p];"."===f?o(i,p):".."===f?(o(i,p),d++):d&&(o(i,p),d--)}if(!u)for(;d--;d)i.unshift("..");!u||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var l=n(8776);function s(e){return"/"===e.charAt(0)?e:"/"+e}function u(e){return"/"===e.charAt(0)?e.substr(1):e}function c(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function f(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach((function(e){return e.apply(void 0,n)}))}}}var g=!("undefined"==typeof window||!window.document||!window.document.createElement);function h(e,t){t(window.confirm(e))}var v="popstate",b="hashchange";function y(){try{return window.history.state||{}}catch(e){return{}}}function w(e){void 0===e&&(e={}),g||(0,l.Z)(!1);var t,n=window.history,a=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=!(-1===window.navigator.userAgent.indexOf("Trident")),i=e,u=i.forceRefresh,w=void 0!==u&&u,k=i.getUserConfirmation,E=void 0===k?h:k,S=i.keyLength,x=void 0===S?6:S,C=e.basename?d(s(e.basename)):"";function _(e){var t=e||{},n=t.key,r=t.state,a=window.location,o=a.pathname+a.search+a.hash;return C&&(o=c(o,C)),f(o,r,n)}function T(){return Math.random().toString(36).substr(2,x)}var A=m();function L(e){(0,r.Z)(U,e),U.length=n.length,A.notifyListeners(U.location,U.action)}function R(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||O(_(e.state))}function P(){O(_(y()))}var N=!1;function O(e){if(N)N=!1,L();else{A.confirmTransitionTo(e,"POP",E,(function(t){t?L({action:"POP",location:e}):function(e){var t=U.location,n=D.indexOf(t.key);-1===n&&(n=0);var r=D.indexOf(e.key);-1===r&&(r=0);var a=n-r;a&&(N=!0,F(a))}(e)}))}}var I=_(y()),D=[I.key];function M(e){return C+p(e)}function F(e){n.go(e)}var j=0;function B(e){1===(j+=e)&&1===e?(window.addEventListener(v,R),o&&window.addEventListener(b,P)):0===j&&(window.removeEventListener(v,R),o&&window.removeEventListener(b,P))}var z=!1;var U={length:n.length,action:"POP",location:I,createHref:M,push:function(e,t){var r="PUSH",o=f(e,t,T(),U.location);A.confirmTransitionTo(o,r,E,(function(e){if(e){var t=M(o),i=o.key,l=o.state;if(a)if(n.pushState({key:i,state:l},null,t),w)window.location.href=t;else{var s=D.indexOf(U.location.key),u=D.slice(0,s+1);u.push(o.key),D=u,L({action:r,location:o})}else window.location.href=t}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,T(),U.location);A.confirmTransitionTo(o,r,E,(function(e){if(e){var t=M(o),i=o.key,l=o.state;if(a)if(n.replaceState({key:i,state:l},null,t),w)window.location.replace(t);else{var s=D.indexOf(U.location.key);-1!==s&&(D[s]=o.key),L({action:r,location:o})}else window.location.replace(t)}}))},go:F,goBack:function(){F(-1)},goForward:function(){F(1)},block:function(e){void 0===e&&(e=!1);var t=A.setPrompt(e);return z||(B(1),z=!0),function(){return z&&(z=!1,B(-1)),t()}},listen:function(e){var t=A.appendListener(e);return B(1),function(){B(-1),t()}}};return U}var k="hashchange",E={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+u(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:u,decodePath:s},slash:{encodePath:s,decodePath:s}};function S(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function x(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function C(e){window.location.replace(S(window.location.href)+"#"+e)}function _(e){void 0===e&&(e={}),g||(0,l.Z)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),a=n.getUserConfirmation,o=void 0===a?h:a,i=n.hashType,u=void 0===i?"slash":i,v=e.basename?d(s(e.basename)):"",b=E[u],y=b.encodePath,w=b.decodePath;function _(){var e=w(x());return v&&(e=c(e,v)),f(e)}var T=m();function A(e){(0,r.Z)(z,e),z.length=t.length,T.notifyListeners(z.location,z.action)}var L=!1,R=null;function P(){var e,t,n=x(),r=y(n);if(n!==r)C(r);else{var a=_(),i=z.location;if(!L&&(t=a,(e=i).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(R===p(a))return;R=null,function(e){if(L)L=!1,A();else{var t="POP";T.confirmTransitionTo(e,t,o,(function(n){n?A({action:t,location:e}):function(e){var t=z.location,n=D.lastIndexOf(p(t));-1===n&&(n=0);var r=D.lastIndexOf(p(e));-1===r&&(r=0);var a=n-r;a&&(L=!0,M(a))}(e)}))}}(a)}}var N=x(),O=y(N);N!==O&&C(O);var I=_(),D=[p(I)];function M(e){t.go(e)}var F=0;function j(e){1===(F+=e)&&1===e?window.addEventListener(k,P):0===F&&window.removeEventListener(k,P)}var B=!1;var z={length:t.length,action:"POP",location:I,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=S(window.location.href)),n+"#"+y(v+p(e))},push:function(e,t){var n="PUSH",r=f(e,void 0,void 0,z.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=p(r),a=y(v+t);if(x()!==a){R=t,function(e){window.location.hash=e}(a);var o=D.lastIndexOf(p(z.location)),i=D.slice(0,o+1);i.push(t),D=i,A({action:n,location:r})}else A()}}))},replace:function(e,t){var n="REPLACE",r=f(e,void 0,void 0,z.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=p(r),a=y(v+t);x()!==a&&(R=t,C(a));var o=D.indexOf(p(z.location));-1!==o&&(D[o]=t),A({action:n,location:r})}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=T.setPrompt(e);return B||(j(1),B=!0),function(){return B&&(B=!1,j(-1)),t()}},listen:function(e){var t=T.appendListener(e);return j(1),function(){j(-1),t()}}};return z}function T(e,t,n){return Math.min(Math.max(e,t),n)}function A(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,a=t.initialEntries,o=void 0===a?["/"]:a,i=t.initialIndex,l=void 0===i?0:i,s=t.keyLength,u=void 0===s?6:s,c=m();function d(e){(0,r.Z)(w,e),w.length=w.entries.length,c.notifyListeners(w.location,w.action)}function g(){return Math.random().toString(36).substr(2,u)}var h=T(l,0,o.length-1),v=o.map((function(e){return f(e,void 0,"string"==typeof e?g():e.key||g())})),b=p;function y(e){var t=T(w.index+e,0,w.entries.length-1),r=w.entries[t];c.confirmTransitionTo(r,"POP",n,(function(e){e?d({action:"POP",location:r,index:t}):d()}))}var w={length:v.length,action:"POP",location:v[h],index:h,entries:v,createHref:b,push:function(e,t){var r="PUSH",a=f(e,t,g(),w.location);c.confirmTransitionTo(a,r,n,(function(e){if(e){var t=w.index+1,n=w.entries.slice(0);n.length>t?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,g(),w.location);c.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t<w.entries.length},block:function(e){return void 0===e&&(e=!1),c.setPrompt(e)},listen:function(e){return c.appendListener(e)}};return w}},8679:(e,t,n)=>{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function s(e){return r.isMemo(e)?i:l[e.$$typeof]||a}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var u=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=f(n);a&&a!==m&&e(t,a,r)}var i=c(n);d&&(i=i.concat(d(n)));for(var l=s(t),g=s(n),h=0;h<i.length;++h){var v=i[h];if(!(o[v]||r&&r[v]||g&&g[v]||l&&l[v])){var b=p(n,v);try{u(t,v,b)}catch(y){}}}}return t}},1143:e=>{"use strict";e.exports=function(e,t,n,r,a,o,i,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,a,o,i,l],c=0;(s=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function a(e,t,n){return e<t?t:e>n?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),u=o.querySelector(r.barSelector),c=r.speed,d=r.easing;return o.offsetWidth,l((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,i(e,c,d)),1===e?(s(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){s(o,{transition:"all "+c+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),c)}),c)):setTimeout(t,c)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),l=e?"-100":o(n.status||0),u=document.querySelector(r.parent);return s(i,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&f(a),u!=document.body&&c(u,"nprogress-custom-parent"),u.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var l=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function u(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=p(e),r=n+t;u(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);u(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,o){for(var i,l,s=a(e),u=1;u<arguments.length;u++){for(var c in i=Object(arguments[u]))n.call(i,c)&&(s[c]=i[c]);if(t){l=t(i);for(var d=0;d<l.length;d++)r.call(i,l[d])&&(s[l[d]]=i[l[d]])}}return s}},7410:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var a,o;switch(n=n||{},r.util.type(t)){case"Object":if(o=r.util.objId(t),n[o])return n[o];for(var i in a={},n[o]=a,t)t.hasOwnProperty(i)&&(a[i]=e(t[i],n));return a;case"Array":return o=r.util.objId(t),n[o]?n[o]:(a=[],n[o]=a,t.forEach((function(t,r){a[r]=e(t,n)})),a);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var a=e.classList;if(a.contains(t))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var a in t)n[a]=t[a];return n},insertBefore:function(e,t,n,a){var o=(a=a||r.languages)[e],i={};for(var l in o)if(o.hasOwnProperty(l)){if(l==t)for(var s in n)n.hasOwnProperty(s)&&(i[s]=n[s]);n.hasOwnProperty(l)||(i[l]=o[l])}var u=a[e];return a[e]=i,r.languages.DFS(r.languages,(function(t,n){n===u&&t!=e&&(this[t]=i)})),i},DFS:function e(t,n,a,o){o=o||{};var i=r.util.objId;for(var l in t)if(t.hasOwnProperty(l)){n.call(t,l,t[l],a||l);var s=t[l],u=r.util.type(s);"Object"!==u||o[i(s)]?"Array"!==u||o[i(s)]||(o[i(s)]=!0,e(s,n,l,o)):(o[i(s)]=!0,e(s,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};return r.hooks.run("before-tokenize",o),o.tokens=r.tokenize(o.code,o.grammar),r.hooks.run("after-tokenize",o),a.stringify(r.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var r in n)t[r]=n[r];delete t.rest}var a=new l;return s(a,a.head,e),i(e,a,t,a.head,0),function(e){var t=[],n=e.head.next;for(;n!==e.tail;)t.push(n.value),n=n.next;return t}(a)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var a,o=0;a=n[o++];)a(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var a=e.exec(n);if(a&&r&&a[1]){var o=a[1].length;a.index+=o,a[0]=a[0].slice(o)}return a}function i(e,t,n,l,c,d){for(var p in n)if(n.hasOwnProperty(p)&&n[p]){var f=n[p];f=Array.isArray(f)?f:[f];for(var m=0;m<f.length;++m){if(d&&d.cause==p+","+m)return;var g=f[m],h=g.inside,v=!!g.lookbehind,b=!!g.greedy,y=g.alias;if(b&&!g.pattern.global){var w=g.pattern.toString().match(/[imsuy]*$/)[0];g.pattern=RegExp(g.pattern.source,w+"g")}for(var k=g.pattern||g,E=l.next,S=c;E!==t.tail&&!(d&&S>=d.reach);S+=E.value.length,E=E.next){var x=E.value;if(t.length>e.length)return;if(!(x instanceof a)){var C,_=1;if(b){if(!(C=o(k,S,e,v))||C.index>=e.length)break;var T=C.index,A=C.index+C[0].length,L=S;for(L+=E.value.length;T>=L;)L+=(E=E.next).value.length;if(S=L-=E.value.length,E.value instanceof a)continue;for(var R=E;R!==t.tail&&(L<A||"string"==typeof R.value);R=R.next)_++,L+=R.value.length;_--,x=e.slice(S,L),C.index-=S}else if(!(C=o(k,0,x,v)))continue;T=C.index;var P=C[0],N=x.slice(0,T),O=x.slice(T+P.length),I=S+x.length;d&&I>d.reach&&(d.reach=I);var D=E.prev;if(N&&(D=s(t,D,N),S+=N.length),u(t,D,_),E=s(t,D,new a(p,h?r.tokenize(P,h):P,y,P)),O&&s(t,E,O),_>1){var M={cause:p+","+m,reach:I};i(e,t,n,E.prev,S,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function s(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function u(e,t,n){for(var r=t.next,a=0;a<n&&r!==e.tail;a++)r=r.next;t.next=r,r.prev=t,e.length-=a}return a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var a="";return t.forEach((function(t){a+=e(t,n)})),a}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(o.classes,i):o.classes.push(i)),r.hooks.run("wrap",o);var l="";for(var s in o.attributes)l+=" "+s+'="'+(o.attributes[s]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+l+">"+o.content+"</"+o.tag+">"},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var r={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i<a.length;i++)o[a[i]]=e.languages.bash[a[i]];e.languages.shell=e.languages.bash}(a),a.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var a=t[n];if("code"===a.type){var o=a.content[1],i=a.content[3];if(o&&i&&"code-language"===o.type&&"code-block"===i.type&&"string"==typeof o.content){var l=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),s="language-"+(l=(/[a-z][\w-]*/i.exec(l)||[""])[0].toLowerCase());i.alias?"string"==typeof i.alias?i.alias=[i.alias,s]:i.alias.push(s):i.alias=[s]}}else e(a.content)}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",r=0,a=t.classes.length;r<a;r++){var o=t.classes[r],u=/language-(.+)/.exec(o);if(u){n=u[1];break}}var c,d=e.languages[n];if(d)t.content=e.highlight((c=t.content,c.replace(i,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;if("#"===(t=t.toLowerCase())[0])return n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),s(n);var r=l[t];return r||e}))),d,n);else if(n&&"none"!==n&&e.plugins.autoloader){var p="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random());t.attributes.id=p,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(p);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))}))}}}));var i=RegExp(e.languages.markup.tag.pattern.source,"gi"),l={amp:"&",lt:"<",gt:">",quot:'"'},s=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var a=[];if(d(["definition-mutation","punctuation"])&&"("===c(1).content){n+=2;var o=p(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var i=c(0);"variable"===i.type&&(f(i,"variable-input"),a.push(i.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===c(0).content&&(n++,f(c(0),"property-mutation"),a.length>0)){var l=p(/^\{$/,/^\}$/);if(-1===l)continue;for(var s=n;s<l;s++){var u=t[s];"variable"===u.type&&a.indexOf(u.content)>=0&&f(u,"variable-input")}}}}function c(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var r=c(n+t);if(!r||r.type!==e[n])return!1}return!0}function p(e,r){for(var a=1,o=n;o<t.length;o++){var i=t[o],l=i.content;if("punctuation"===i.type&&"string"==typeof l)if(e.test(l))a++;else if(r.test(l)&&0===--a)return o}return-1}function f(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),a.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function l(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function s(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function u(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,s(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function c(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,c={},d=s(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=l(i++,r)););return c[n]=a,n})).join(""),n,r),p=Object.keys(c);return i=0,function e(t){for(var n=0;n<t.length;n++){if(i>=p.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=p[i],o="string"==typeof r?r:r.content,l=o.indexOf(a);if(-1!==l){++i;var s=o.substring(0,l),d=u(c[a]),f=o.substring(l+a.length),m=[];if(s&&m.push(s),m.push(d),f){var g=[f];e(g),m.push.apply(m,g)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var h=r.content;Array.isArray(h)?e(h):e([h])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function p(e){return"string"==typeof e?e:Array.isArray(e)?e.map(p).join(""):p(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r<a;r++){var o=n[r];if("string"!=typeof o){var i=o.content;if(Array.isArray(i))if("template-string"===o.type){var l=i[1];if(3===i.length&&"string"!=typeof l&&"embedded-code"===l.type){var s=p(l),u=l.alias,d=Array.isArray(u)?u[0]:u,f=e.languages[d];if(!f)continue;i[1]=c(s,f,d)}}else t(i);else"string"!=typeof i&&t([i])}}}(t.tokens)}))}(a),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var a=n[r],o=e.languages.javascript[a];"RegExp"===e.util.type(o)&&(o=e.languages.javascript[a]={pattern:o});var i=o.inside||{};o.inside=i,i["maybe-class-name"]=/^[A-Z][\s\S]*/}}(a),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return r})).replace(/<SPREAD>/g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},l=function(t){for(var n=[],r=0;r<t.length;r++){var a=t[r],o=!1;if("string"!=typeof a&&("tag"===a.type&&a.content[0]&&"tag"===a.content[0].type?"</"===a.content[0].content[0].content?n.length>0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var s=i(a);r<t.length-1&&("string"==typeof t[r+1]||"plain-text"===t[r+1].type)&&(s+=i(t[r+1]),t.splice(r+1,1)),r>0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(s=i(t[r-1])+s,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",s,null,s)}a.content&&"string"!=typeof a.content&&l(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||l(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,l=i.length;-1!==n.code.indexOf(a=t(r,l));)++l;return i[l]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(l){for(var s=0;s<l.length&&!(a>=o.length);s++){var u=l[s];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=o[a],d=n.tokenStack[c],p="string"==typeof u?u:u.content,f=t(r,c),m=p.indexOf(f);if(m>-1){++a;var g=p.substring(0,m),h=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),v=p.substring(m+f.length),b=[];g&&b.push.apply(b,i([g])),b.push(h),v&&b.push.apply(b,i([v])),"string"==typeof u?l.splice.apply(l,[s,1].concat(b)):u.content=b}}else u.content&&i(u.content)}return l}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to <a href="https://webplatform.github.io/docs/">WebPlatform.org documentation</a>. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (<code>.comment</code> can become <code>.namespace--comment</code>) or replace them with your defined ones (like <code>.editor__comment</code>). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the <code>highlightAll</code> and <code>highlightAllUnder</code> methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n]]=!0;return t}function r(e){var n={},r=[];function a(r,o){if(!(r in n)){o.push(r);var i=o.indexOf(r);if(i<o.length-1)throw new Error("Circular dependency: "+o.slice(i).join(" -> "));var l={},s=e[r];if(s){function u(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in l))for(var i in a(t,o),l[t]=!0,n[t])l[i]=!0}t(s.require,u),t(s.optional,u),t(s.modify,u)}n[r]=l,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,l){var s=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),u=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(s);i=i.map(u),l=(l||[]).map(u);var c=n(i),d=n(l);i.forEach((function e(n){var r=s[n];t(r&&r.require,(function(t){t in d||(c[t]=!0,e(t))}))}));for(var p,f=r(s),m=c;a(m);){for(var g in p={},m){var h=s[g];t(h&&h.modify,(function(e){e in d&&(p[e]=!0)}))}for(var v in d)if(!(v in c))for(var b in f(v))if(b in c){p[v]=!0;break}for(var y in m=p)c[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,l={},s={};function u(e){if(e in l)return l[e];s[e]=!0;var a,c=[];for(var d in t(e))d in n&&c.push(d);if(0===c.length)a=r(e);else{var p=i(c.map((function(e){var t=u(e);return delete s[e],t})));o?a=o(p,(function(){return r(e)})):r(e)}return l[e]=a}for(var c in n)u(c);var d=[];for(var p in s)d.push(l[p]);return i(d)}(f,c,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!r)throw Error(i(227));var l=new Set,s={};function u(e,t){c(e,t),c(e+"Capture",t)}function c(e,t){for(s[e]=t,e=0;e<t.length;e++)l.add(t[e])}var d=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),p=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,f=Object.prototype.hasOwnProperty,m={},g={};function h(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var v={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){v[e]=new h(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];v[t]=new h(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){v[e]=new h(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){v[e]=new h(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){v[e]=new h(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){v[e]=new h(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){v[e]=new h(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){v[e]=new h(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){v[e]=new h(e,5,!1,e.toLowerCase(),null,!1,!1)}));var b=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function w(e,t,n,r){var a=v.hasOwnProperty(t)?v[t]:null;(null!==a?0===a.type:!r&&(2<t.length&&("o"===t[0]||"O"===t[0])&&("n"===t[1]||"N"===t[1])))||(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,a,r)&&(n=null),r||null===a?function(e){return!!f.call(g,e)||!f.call(m,e)&&(p.test(e)?g[e]=!0:(m[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):a.mustUseProperty?e[a.propertyName]=null===n?3!==a.type&&"":n:(t=a.attributeName,r=a.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(a=a.type)||4===a&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(b,y);v[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(b,y);v[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(b,y);v[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){v[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),v.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){v[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var k=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,E=60103,S=60106,x=60107,C=60108,_=60114,T=60109,A=60110,L=60112,R=60113,P=60120,N=60115,O=60116,I=60121,D=60128,M=60129,F=60130,j=60131;if("function"==typeof Symbol&&Symbol.for){var B=Symbol.for;E=B("react.element"),S=B("react.portal"),x=B("react.fragment"),C=B("react.strict_mode"),_=B("react.profiler"),T=B("react.provider"),A=B("react.context"),L=B("react.forward_ref"),R=B("react.suspense"),P=B("react.suspense_list"),N=B("react.memo"),O=B("react.lazy"),I=B("react.block"),B("react.scope"),D=B("react.opaque.id"),M=B("react.debug_trace_mode"),F=B("react.offscreen"),j=B("react.legacy_hidden")}var z,U="function"==typeof Symbol&&Symbol.iterator;function $(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=U&&e[U]||e["@@iterator"])?e:null}function q(e){if(void 0===z)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);z=t&&t[1]||""}return"\n"+z+e}var G=!1;function H(e,t){if(!e||G)return"";G=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(s){var r=s}Reflect.construct(e,[],t)}else{try{t.call()}catch(s){r=s}e.call(t.prototype)}else{try{throw Error()}catch(s){r=s}e()}}catch(s){if(s&&r&&"string"==typeof s.stack){for(var a=s.stack.split("\n"),o=r.stack.split("\n"),i=a.length-1,l=o.length-1;1<=i&&0<=l&&a[i]!==o[l];)l--;for(;1<=i&&0<=l;i--,l--)if(a[i]!==o[l]){if(1!==i||1!==l)do{if(i--,0>--l||a[i]!==o[l])return"\n"+a[i].replace(" at new "," at ")}while(1<=i&&0<=l);break}}}finally{G=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?q(e):""}function Z(e){switch(e.tag){case 5:return q(e.type);case 16:return q("Lazy");case 13:return q("Suspense");case 19:return q("SuspenseList");case 0:case 2:case 15:return e=H(e.type,!1);case 11:return e=H(e.type.render,!1);case 22:return e=H(e.type._render,!1);case 1:return e=H(e.type,!0);default:return""}}function V(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case x:return"Fragment";case S:return"Portal";case _:return"Profiler";case C:return"StrictMode";case R:return"Suspense";case P:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case A:return(e.displayName||"Context")+".Consumer";case T:return(e._context.displayName||"Context")+".Provider";case L:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case N:return V(e.type);case I:return V(e._render);case O:t=e._payload,e=e._init;try{return V(e(t))}catch(n){}}return null}function W(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function Y(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function K(e){e._valueTracker||(e._valueTracker=function(e){var t=Y(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var a=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(e){r=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function Q(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Y(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function X(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function J(e,t){var n=t.checked;return a({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function ee(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=W(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function te(e,t){null!=(t=t.checked)&&w(e,"checked",t,!1)}function ne(e,t){te(e,t);var n=W(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ae(e,t.type,n):t.hasOwnProperty("defaultValue")&&ae(e,t.type,W(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function re(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ae(e,t,n){"number"===t&&X(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}function oe(e,t){return e=a({children:void 0},t),(t=function(e){var t="";return r.Children.forEach(e,(function(e){null!=e&&(t+=e)})),t}(t.children))&&(e.children=t),e}function ie(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a<n.length;a++)t["$"+n[a]]=!0;for(n=0;n<e.length;n++)a=t.hasOwnProperty("$"+e[n].value),e[n].selected!==a&&(e[n].selected=a),a&&r&&(e[n].defaultSelected=!0)}else{for(n=""+W(n),t=null,a=0;a<e.length;a++){if(e[a].value===n)return e[a].selected=!0,void(r&&(e[a].defaultSelected=!0));null!==t||e[a].disabled||(t=e[a])}null!==t&&(t.selected=!0)}}function le(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(i(91));return a({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function se(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(i(92));if(Array.isArray(n)){if(!(1>=n.length))throw Error(i(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:W(n)}}function ue(e,t){var n=W(t.value),r=W(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ce(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}var de="http://www.w3.org/1999/xhtml",pe="http://www.w3.org/2000/svg";function fe(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function me(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?fe(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var ge,he,ve=(he=function(e,t){if(e.namespaceURI!==pe||"innerHTML"in e)e.innerHTML=t;else{for((ge=ge||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=ge.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return he(e,t)}))}:he);function be(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ye={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},we=["Webkit","ms","Moz","O"];function ke(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||ye.hasOwnProperty(e)&&ye[e]?(""+t).trim():t+"px"}function Ee(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),a=ke(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}Object.keys(ye).forEach((function(e){we.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ye[t]=ye[e]}))}));var Se=a({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function xe(e,t){if(t){if(Se[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(i(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(i(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(i(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(i(62))}}function Ce(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function _e(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var Te=null,Ae=null,Le=null;function Re(e){if(e=ra(e)){if("function"!=typeof Te)throw Error(i(280));var t=e.stateNode;t&&(t=oa(t),Te(e.stateNode,e.type,t))}}function Pe(e){Ae?Le?Le.push(e):Le=[e]:Ae=e}function Ne(){if(Ae){var e=Ae,t=Le;if(Le=Ae=null,Re(e),t)for(e=0;e<t.length;e++)Re(t[e])}}function Oe(e,t){return e(t)}function Ie(e,t,n,r,a){return e(t,n,r,a)}function De(){}var Me=Oe,Fe=!1,je=!1;function Be(){null===Ae&&null===Le||(De(),Ne())}function ze(e,t){var n=e.stateNode;if(null===n)return null;var r=oa(n);if(null===r)return null;n=r[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(i(231,t,typeof n));return n}var Ue=!1;if(d)try{var $e={};Object.defineProperty($e,"passive",{get:function(){Ue=!0}}),window.addEventListener("test",$e,$e),window.removeEventListener("test",$e,$e)}catch(he){Ue=!1}function qe(e,t,n,r,a,o,i,l,s){var u=Array.prototype.slice.call(arguments,3);try{t.apply(n,u)}catch(c){this.onError(c)}}var Ge=!1,He=null,Ze=!1,Ve=null,We={onError:function(e){Ge=!0,He=e}};function Ye(e,t,n,r,a,o,i,l,s){Ge=!1,He=null,qe.apply(We,arguments)}function Ke(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{0!=(1026&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function Qe(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function Xe(e){if(Ke(e)!==e)throw Error(i(188))}function Je(e){if(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ke(e)))throw Error(i(188));return t!==e?null:e}for(var n=e,r=t;;){var a=n.return;if(null===a)break;var o=a.alternate;if(null===o){if(null!==(r=a.return)){n=r;continue}break}if(a.child===o.child){for(o=a.child;o;){if(o===n)return Xe(a),e;if(o===r)return Xe(a),t;o=o.sibling}throw Error(i(188))}if(n.return!==r.return)n=a,r=o;else{for(var l=!1,s=a.child;s;){if(s===n){l=!0,n=a,r=o;break}if(s===r){l=!0,r=a,n=o;break}s=s.sibling}if(!l){for(s=o.child;s;){if(s===n){l=!0,n=o,r=a;break}if(s===r){l=!0,r=o,n=a;break}s=s.sibling}if(!l)throw Error(i(189))}}if(n.alternate!==r)throw Error(i(190))}if(3!==n.tag)throw Error(i(188));return n.stateNode.current===n?e:t}(e),!e)return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}function et(e,t){for(var n=e.alternate;null!==t;){if(t===e||t===n)return!0;t=t.return}return!1}var tt,nt,rt,at,ot=!1,it=[],lt=null,st=null,ut=null,ct=new Map,dt=new Map,pt=[],ft="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function mt(e,t,n,r,a){return{blockedOn:e,domEventName:t,eventSystemFlags:16|n,nativeEvent:a,targetContainers:[r]}}function gt(e,t){switch(e){case"focusin":case"focusout":lt=null;break;case"dragenter":case"dragleave":st=null;break;case"mouseover":case"mouseout":ut=null;break;case"pointerover":case"pointerout":ct.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":dt.delete(t.pointerId)}}function ht(e,t,n,r,a,o){return null===e||e.nativeEvent!==o?(e=mt(t,n,r,a,o),null!==t&&(null!==(t=ra(t))&&nt(t)),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==a&&-1===t.indexOf(a)&&t.push(a),e)}function vt(e){var t=na(e.target);if(null!==t){var n=Ke(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=Qe(n)))return e.blockedOn=t,void at(e.lanePriority,(function(){o.unstable_runWithPriority(e.priority,(function(){rt(n)}))}))}else if(3===t&&n.stateNode.hydrate)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function bt(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Jt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=ra(n))&&nt(t),e.blockedOn=n,!1;t.shift()}return!0}function yt(e,t,n){bt(e)&&n.delete(t)}function wt(){for(ot=!1;0<it.length;){var e=it[0];if(null!==e.blockedOn){null!==(e=ra(e.blockedOn))&&tt(e);break}for(var t=e.targetContainers;0<t.length;){var n=Jt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n){e.blockedOn=n;break}t.shift()}null===e.blockedOn&&it.shift()}null!==lt&&bt(lt)&&(lt=null),null!==st&&bt(st)&&(st=null),null!==ut&&bt(ut)&&(ut=null),ct.forEach(yt),dt.forEach(yt)}function kt(e,t){e.blockedOn===t&&(e.blockedOn=null,ot||(ot=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,wt)))}function Et(e){function t(t){return kt(t,e)}if(0<it.length){kt(it[0],e);for(var n=1;n<it.length;n++){var r=it[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==lt&&kt(lt,e),null!==st&&kt(st,e),null!==ut&&kt(ut,e),ct.forEach(t),dt.forEach(t),n=0;n<pt.length;n++)(r=pt[n]).blockedOn===e&&(r.blockedOn=null);for(;0<pt.length&&null===(n=pt[0]).blockedOn;)vt(n),null===n.blockedOn&&pt.shift()}function St(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var xt={animationend:St("Animation","AnimationEnd"),animationiteration:St("Animation","AnimationIteration"),animationstart:St("Animation","AnimationStart"),transitionend:St("Transition","TransitionEnd")},Ct={},_t={};function Tt(e){if(Ct[e])return Ct[e];if(!xt[e])return e;var t,n=xt[e];for(t in n)if(n.hasOwnProperty(t)&&t in _t)return Ct[e]=n[t];return e}d&&(_t=document.createElement("div").style,"AnimationEvent"in window||(delete xt.animationend.animation,delete xt.animationiteration.animation,delete xt.animationstart.animation),"TransitionEvent"in window||delete xt.transitionend.transition);var At=Tt("animationend"),Lt=Tt("animationiteration"),Rt=Tt("animationstart"),Pt=Tt("transitionend"),Nt=new Map,Ot=new Map,It=["abort","abort",At,"animationEnd",Lt,"animationIteration",Rt,"animationStart","canplay","canPlay","canplaythrough","canPlayThrough","durationchange","durationChange","emptied","emptied","encrypted","encrypted","ended","ended","error","error","gotpointercapture","gotPointerCapture","load","load","loadeddata","loadedData","loadedmetadata","loadedMetadata","loadstart","loadStart","lostpointercapture","lostPointerCapture","playing","playing","progress","progress","seeking","seeking","stalled","stalled","suspend","suspend","timeupdate","timeUpdate",Pt,"transitionEnd","waiting","waiting"];function Dt(e,t){for(var n=0;n<e.length;n+=2){var r=e[n],a=e[n+1];a="on"+(a[0].toUpperCase()+a.slice(1)),Ot.set(r,t),Nt.set(r,a),u(a,[r])}}(0,o.unstable_now)();var Mt=8;function Ft(e){if(0!=(1&e))return Mt=15,1;if(0!=(2&e))return Mt=14,2;if(0!=(4&e))return Mt=13,4;var t=24&e;return 0!==t?(Mt=12,t):0!=(32&e)?(Mt=11,32):0!==(t=192&e)?(Mt=10,t):0!=(256&e)?(Mt=9,256):0!==(t=3584&e)?(Mt=8,t):0!=(4096&e)?(Mt=7,4096):0!==(t=4186112&e)?(Mt=6,t):0!==(t=62914560&e)?(Mt=5,t):67108864&e?(Mt=4,67108864):0!=(134217728&e)?(Mt=3,134217728):0!==(t=805306368&e)?(Mt=2,t):0!=(1073741824&e)?(Mt=1,1073741824):(Mt=8,e)}function jt(e,t){var n=e.pendingLanes;if(0===n)return Mt=0;var r=0,a=0,o=e.expiredLanes,i=e.suspendedLanes,l=e.pingedLanes;if(0!==o)r=o,a=Mt=15;else if(0!==(o=134217727&n)){var s=o&~i;0!==s?(r=Ft(s),a=Mt):0!==(l&=o)&&(r=Ft(l),a=Mt)}else 0!==(o=n&~i)?(r=Ft(o),a=Mt):0!==l&&(r=Ft(l),a=Mt);if(0===r)return 0;if(r=n&((0>(r=31-Gt(r))?0:1<<r)<<1)-1,0!==t&&t!==r&&0==(t&i)){if(Ft(t),a<=Mt)return t;Mt=a}if(0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)a=1<<(n=31-Gt(t)),r|=e[n],t&=~a;return r}function Bt(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function zt(e,t){switch(e){case 15:return 1;case 14:return 2;case 12:return 0===(e=Ut(24&~t))?zt(10,t):e;case 10:return 0===(e=Ut(192&~t))?zt(8,t):e;case 8:return 0===(e=Ut(3584&~t))&&(0===(e=Ut(4186112&~t))&&(e=512)),e;case 2:return 0===(t=Ut(805306368&~t))&&(t=268435456),t}throw Error(i(358,e))}function Ut(e){return e&-e}function $t(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function qt(e,t,n){e.pendingLanes|=t;var r=t-1;e.suspendedLanes&=r,e.pingedLanes&=r,(e=e.eventTimes)[t=31-Gt(t)]=n}var Gt=Math.clz32?Math.clz32:function(e){return 0===e?32:31-(Ht(e)/Zt|0)|0},Ht=Math.log,Zt=Math.LN2;var Vt=o.unstable_UserBlockingPriority,Wt=o.unstable_runWithPriority,Yt=!0;function Kt(e,t,n,r){Fe||De();var a=Xt,o=Fe;Fe=!0;try{Ie(a,e,t,n,r)}finally{(Fe=o)||Be()}}function Qt(e,t,n,r){Wt(Vt,Xt.bind(null,e,t,n,r))}function Xt(e,t,n,r){var a;if(Yt)if((a=0==(4&t))&&0<it.length&&-1<ft.indexOf(e))e=mt(null,e,t,n,r),it.push(e);else{var o=Jt(e,t,n,r);if(null===o)a&>(e,r);else{if(a){if(-1<ft.indexOf(e))return e=mt(o,e,t,n,r),void it.push(e);if(function(e,t,n,r,a){switch(t){case"focusin":return lt=ht(lt,e,t,n,r,a),!0;case"dragenter":return st=ht(st,e,t,n,r,a),!0;case"mouseover":return ut=ht(ut,e,t,n,r,a),!0;case"pointerover":var o=a.pointerId;return ct.set(o,ht(ct.get(o)||null,e,t,n,r,a)),!0;case"gotpointercapture":return o=a.pointerId,dt.set(o,ht(dt.get(o)||null,e,t,n,r,a)),!0}return!1}(o,e,t,n,r))return;gt(e,r)}Dr(e,t,r,null,n)}}}function Jt(e,t,n,r){var a=_e(r);if(null!==(a=na(a))){var o=Ke(a);if(null===o)a=null;else{var i=o.tag;if(13===i){if(null!==(a=Qe(o)))return a;a=null}else if(3===i){if(o.stateNode.hydrate)return 3===o.tag?o.stateNode.containerInfo:null;a=null}else o!==a&&(a=null)}}return Dr(e,t,r,a,n),null}var en=null,tn=null,nn=null;function rn(){if(nn)return nn;var e,t,n=tn,r=n.length,a="value"in en?en.value:en.textContent,o=a.length;for(e=0;e<r&&n[e]===a[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===a[o-t];t++);return nn=a.slice(e,1<t?1-t:void 0)}function an(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function on(){return!0}function ln(){return!1}function sn(e){function t(t,n,r,a,o){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=a,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(a):a[i]);return this.isDefaultPrevented=(null!=a.defaultPrevented?a.defaultPrevented:!1===a.returnValue)?on:ln,this.isPropagationStopped=ln,this}return a(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=on)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=on)},persist:function(){},isPersistent:on}),t}var un,cn,dn,pn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},fn=sn(pn),mn=a({},pn,{view:0,detail:0}),gn=sn(mn),hn=a({},mn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:An,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==dn&&(dn&&"mousemove"===e.type?(un=e.screenX-dn.screenX,cn=e.screenY-dn.screenY):cn=un=0,dn=e),un)},movementY:function(e){return"movementY"in e?e.movementY:cn}}),vn=sn(hn),bn=sn(a({},hn,{dataTransfer:0})),yn=sn(a({},mn,{relatedTarget:0})),wn=sn(a({},pn,{animationName:0,elapsedTime:0,pseudoElement:0})),kn=a({},pn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),En=sn(kn),Sn=sn(a({},pn,{data:0})),xn={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},Cn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},_n={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function Tn(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=_n[e])&&!!t[e]}function An(){return Tn}var Ln=a({},mn,{key:function(e){if(e.key){var t=xn[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=an(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?Cn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:An,charCode:function(e){return"keypress"===e.type?an(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?an(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),Rn=sn(Ln),Pn=sn(a({},hn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),Nn=sn(a({},mn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:An})),On=sn(a({},pn,{propertyName:0,elapsedTime:0,pseudoElement:0})),In=a({},hn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),Dn=sn(In),Mn=[9,13,27,32],Fn=d&&"CompositionEvent"in window,jn=null;d&&"documentMode"in document&&(jn=document.documentMode);var Bn=d&&"TextEvent"in window&&!jn,zn=d&&(!Fn||jn&&8<jn&&11>=jn),Un=String.fromCharCode(32),$n=!1;function qn(e,t){switch(e){case"keyup":return-1!==Mn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Gn(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Hn=!1;var Zn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Vn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Zn[e.type]:"textarea"===t}function Wn(e,t,n,r){Pe(r),0<(t=Fr(t,"onChange")).length&&(n=new fn("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Yn=null,Kn=null;function Qn(e){Lr(e,0)}function Xn(e){if(Q(aa(e)))return e}function Jn(e,t){if("change"===e)return t}var er=!1;if(d){var tr;if(d){var nr="oninput"in document;if(!nr){var rr=document.createElement("div");rr.setAttribute("oninput","return;"),nr="function"==typeof rr.oninput}tr=nr}else tr=!1;er=tr&&(!document.documentMode||9<document.documentMode)}function ar(){Yn&&(Yn.detachEvent("onpropertychange",or),Kn=Yn=null)}function or(e){if("value"===e.propertyName&&Xn(Kn)){var t=[];if(Wn(t,Kn,e,_e(e)),e=Qn,Fe)e(t);else{Fe=!0;try{Oe(e,t)}finally{Fe=!1,Be()}}}}function ir(e,t,n){"focusin"===e?(ar(),Kn=n,(Yn=t).attachEvent("onpropertychange",or)):"focusout"===e&&ar()}function lr(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Xn(Kn)}function sr(e,t){if("click"===e)return Xn(t)}function ur(e,t){if("input"===e||"change"===e)return Xn(t)}var cr="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},dr=Object.prototype.hasOwnProperty;function pr(e,t){if(cr(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++)if(!dr.call(t,n[r])||!cr(e[n[r]],t[n[r]]))return!1;return!0}function fr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function mr(e,t){var n,r=fr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=fr(r)}}function gr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?gr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function hr(){for(var e=window,t=X();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=X((e=t.contentWindow).document)}return t}function vr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var br=d&&"documentMode"in document&&11>=document.documentMode,yr=null,wr=null,kr=null,Er=!1;function Sr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;Er||null==yr||yr!==X(r)||("selectionStart"in(r=yr)&&vr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},kr&&pr(kr,r)||(kr=r,0<(r=Fr(wr,"onSelect")).length&&(t=new fn("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=yr)))}Dt("cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),0),Dt("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1),Dt(It,2);for(var xr="change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),Cr=0;Cr<xr.length;Cr++)Ot.set(xr[Cr],0);c("onMouseEnter",["mouseout","mouseover"]),c("onMouseLeave",["mouseout","mouseover"]),c("onPointerEnter",["pointerout","pointerover"]),c("onPointerLeave",["pointerout","pointerover"]),u("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),u("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),u("onBeforeInput",["compositionend","keypress","textInput","paste"]),u("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),u("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),u("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var _r="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Tr=new Set("cancel close invalid load scroll toggle".split(" ").concat(_r));function Ar(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,r,a,o,l,s,u){if(Ye.apply(this,arguments),Ge){if(!Ge)throw Error(i(198));var c=He;Ge=!1,He=null,Ze||(Ze=!0,Ve=c)}}(r,t,void 0,e),e.currentTarget=null}function Lr(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var r=e[n],a=r.event;r=r.listeners;e:{var o=void 0;if(t)for(var i=r.length-1;0<=i;i--){var l=r[i],s=l.instance,u=l.currentTarget;if(l=l.listener,s!==o&&a.isPropagationStopped())break e;Ar(a,l,u),o=s}else for(i=0;i<r.length;i++){if(s=(l=r[i]).instance,u=l.currentTarget,l=l.listener,s!==o&&a.isPropagationStopped())break e;Ar(a,l,u),o=s}}}if(Ze)throw e=Ve,Ze=!1,Ve=null,e}function Rr(e,t){var n=ia(t),r=e+"__bubble";n.has(r)||(Ir(t,e,2,!1),n.add(r))}var Pr="_reactListening"+Math.random().toString(36).slice(2);function Nr(e){e[Pr]||(e[Pr]=!0,l.forEach((function(t){Tr.has(t)||Or(t,!1,e,null),Or(t,!0,e,null)})))}function Or(e,t,n,r){var a=4<arguments.length&&void 0!==arguments[4]?arguments[4]:0,o=n;if("selectionchange"===e&&9!==n.nodeType&&(o=n.ownerDocument),null!==r&&!t&&Tr.has(e)){if("scroll"!==e)return;a|=2,o=r}var i=ia(o),l=e+"__"+(t?"capture":"bubble");i.has(l)||(t&&(a|=4),Ir(o,e,a,t),i.add(l))}function Ir(e,t,n,r){var a=Ot.get(t);switch(void 0===a?2:a){case 0:a=Kt;break;case 1:a=Qt;break;default:a=Xt}n=a.bind(null,t,n,e),a=void 0,!Ue||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(a=!0),r?void 0!==a?e.addEventListener(t,n,{capture:!0,passive:a}):e.addEventListener(t,n,!0):void 0!==a?e.addEventListener(t,n,{passive:a}):e.addEventListener(t,n,!1)}function Dr(e,t,n,r,a){var o=r;if(0==(1&t)&&0==(2&t)&&null!==r)e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var l=r.stateNode.containerInfo;if(l===a||8===l.nodeType&&l.parentNode===a)break;if(4===i)for(i=r.return;null!==i;){var s=i.tag;if((3===s||4===s)&&((s=i.stateNode.containerInfo)===a||8===s.nodeType&&s.parentNode===a))return;i=i.return}for(;null!==l;){if(null===(i=na(l)))return;if(5===(s=i.tag)||6===s){r=o=i;continue e}l=l.parentNode}}r=r.return}!function(e,t,n){if(je)return e(t,n);je=!0;try{Me(e,t,n)}finally{je=!1,Be()}}((function(){var r=o,a=_e(n),i=[];e:{var l=Nt.get(e);if(void 0!==l){var s=fn,u=e;switch(e){case"keypress":if(0===an(n))break e;case"keydown":case"keyup":s=Rn;break;case"focusin":u="focus",s=yn;break;case"focusout":u="blur",s=yn;break;case"beforeblur":case"afterblur":s=yn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":s=vn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":s=bn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":s=Nn;break;case At:case Lt:case Rt:s=wn;break;case Pt:s=On;break;case"scroll":s=gn;break;case"wheel":s=Dn;break;case"copy":case"cut":case"paste":s=En;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":s=Pn}var c=0!=(4&t),d=!c&&"scroll"===e,p=c?null!==l?l+"Capture":null:l;c=[];for(var f,m=r;null!==m;){var g=(f=m).stateNode;if(5===f.tag&&null!==g&&(f=g,null!==p&&(null!=(g=ze(m,p))&&c.push(Mr(m,g,f)))),d)break;m=m.return}0<c.length&&(l=new s(l,u,null,n,a),i.push({event:l,listeners:c}))}}if(0==(7&t)){if(s="mouseout"===e||"pointerout"===e,(!(l="mouseover"===e||"pointerover"===e)||0!=(16&t)||!(u=n.relatedTarget||n.fromElement)||!na(u)&&!u[ea])&&(s||l)&&(l=a.window===a?a:(l=a.ownerDocument)?l.defaultView||l.parentWindow:window,s?(s=r,null!==(u=(u=n.relatedTarget||n.toElement)?na(u):null)&&(u!==(d=Ke(u))||5!==u.tag&&6!==u.tag)&&(u=null)):(s=null,u=r),s!==u)){if(c=vn,g="onMouseLeave",p="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(c=Pn,g="onPointerLeave",p="onPointerEnter",m="pointer"),d=null==s?l:aa(s),f=null==u?l:aa(u),(l=new c(g,m+"leave",s,n,a)).target=d,l.relatedTarget=f,g=null,na(a)===r&&((c=new c(p,m+"enter",u,n,a)).target=f,c.relatedTarget=d,g=c),d=g,s&&u)e:{for(p=u,m=0,f=c=s;f;f=jr(f))m++;for(f=0,g=p;g;g=jr(g))f++;for(;0<m-f;)c=jr(c),m--;for(;0<f-m;)p=jr(p),f--;for(;m--;){if(c===p||null!==p&&c===p.alternate)break e;c=jr(c),p=jr(p)}c=null}else c=null;null!==s&&Br(i,l,s,c,!1),null!==u&&null!==d&&Br(i,d,u,c,!0)}if("select"===(s=(l=r?aa(r):window).nodeName&&l.nodeName.toLowerCase())||"input"===s&&"file"===l.type)var h=Jn;else if(Vn(l))if(er)h=ur;else{h=lr;var v=ir}else(s=l.nodeName)&&"input"===s.toLowerCase()&&("checkbox"===l.type||"radio"===l.type)&&(h=sr);switch(h&&(h=h(e,r))?Wn(i,h,n,a):(v&&v(e,l,r),"focusout"===e&&(v=l._wrapperState)&&v.controlled&&"number"===l.type&&ae(l,"number",l.value)),v=r?aa(r):window,e){case"focusin":(Vn(v)||"true"===v.contentEditable)&&(yr=v,wr=r,kr=null);break;case"focusout":kr=wr=yr=null;break;case"mousedown":Er=!0;break;case"contextmenu":case"mouseup":case"dragend":Er=!1,Sr(i,n,a);break;case"selectionchange":if(br)break;case"keydown":case"keyup":Sr(i,n,a)}var b;if(Fn)e:{switch(e){case"compositionstart":var y="onCompositionStart";break e;case"compositionend":y="onCompositionEnd";break e;case"compositionupdate":y="onCompositionUpdate";break e}y=void 0}else Hn?qn(e,n)&&(y="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(y="onCompositionStart");y&&(zn&&"ko"!==n.locale&&(Hn||"onCompositionStart"!==y?"onCompositionEnd"===y&&Hn&&(b=rn()):(tn="value"in(en=a)?en.value:en.textContent,Hn=!0)),0<(v=Fr(r,y)).length&&(y=new Sn(y,e,null,n,a),i.push({event:y,listeners:v}),b?y.data=b:null!==(b=Gn(n))&&(y.data=b))),(b=Bn?function(e,t){switch(e){case"compositionend":return Gn(t);case"keypress":return 32!==t.which?null:($n=!0,Un);case"textInput":return(e=t.data)===Un&&$n?null:e;default:return null}}(e,n):function(e,t){if(Hn)return"compositionend"===e||!Fn&&qn(e,t)?(e=rn(),nn=tn=en=null,Hn=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return zn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(r=Fr(r,"onBeforeInput")).length&&(a=new Sn("onBeforeInput","beforeinput",null,n,a),i.push({event:a,listeners:r}),a.data=b))}Lr(i,t)}))}function Mr(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Fr(e,t){for(var n=t+"Capture",r=[];null!==e;){var a=e,o=a.stateNode;5===a.tag&&null!==o&&(a=o,null!=(o=ze(e,n))&&r.unshift(Mr(e,o,a)),null!=(o=ze(e,t))&&r.push(Mr(e,o,a))),e=e.return}return r}function jr(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Br(e,t,n,r,a){for(var o=t._reactName,i=[];null!==n&&n!==r;){var l=n,s=l.alternate,u=l.stateNode;if(null!==s&&s===r)break;5===l.tag&&null!==u&&(l=u,a?null!=(s=ze(n,o))&&i.unshift(Mr(n,s,l)):a||null!=(s=ze(n,o))&&i.push(Mr(n,s,l))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}function zr(){}var Ur=null,$r=null;function qr(e,t){switch(e){case"button":case"input":case"select":case"textarea":return!!t.autoFocus}return!1}function Gr(e,t){return"textarea"===e||"option"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var Hr="function"==typeof setTimeout?setTimeout:void 0,Zr="function"==typeof clearTimeout?clearTimeout:void 0;function Vr(e){1===e.nodeType?e.textContent="":9===e.nodeType&&(null!=(e=e.body)&&(e.textContent=""))}function Wr(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break}return e}function Yr(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var Kr=0;var Qr=Math.random().toString(36).slice(2),Xr="__reactFiber$"+Qr,Jr="__reactProps$"+Qr,ea="__reactContainer$"+Qr,ta="__reactEvents$"+Qr;function na(e){var t=e[Xr];if(t)return t;for(var n=e.parentNode;n;){if(t=n[ea]||n[Xr]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=Yr(e);null!==e;){if(n=e[Xr])return n;e=Yr(e)}return t}n=(e=n).parentNode}return null}function ra(e){return!(e=e[Xr]||e[ea])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function aa(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(i(33))}function oa(e){return e[Jr]||null}function ia(e){var t=e[ta];return void 0===t&&(t=e[ta]=new Set),t}var la=[],sa=-1;function ua(e){return{current:e}}function ca(e){0>sa||(e.current=la[sa],la[sa]=null,sa--)}function da(e,t){sa++,la[sa]=e.current,e.current=t}var pa={},fa=ua(pa),ma=ua(!1),ga=pa;function ha(e,t){var n=e.type.contextTypes;if(!n)return pa;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a,o={};for(a in n)o[a]=t[a];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function va(e){return null!=(e=e.childContextTypes)}function ba(){ca(ma),ca(fa)}function ya(e,t,n){if(fa.current!==pa)throw Error(i(168));da(fa,t),da(ma,n)}function wa(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in e))throw Error(i(108,V(t)||"Unknown",o));return a({},n,r)}function ka(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||pa,ga=fa.current,da(fa,e),da(ma,ma.current),!0}function Ea(e,t,n){var r=e.stateNode;if(!r)throw Error(i(169));n?(e=wa(e,t,ga),r.__reactInternalMemoizedMergedChildContext=e,ca(ma),ca(fa),da(fa,e)):ca(ma),da(ma,n)}var Sa=null,xa=null,Ca=o.unstable_runWithPriority,_a=o.unstable_scheduleCallback,Ta=o.unstable_cancelCallback,Aa=o.unstable_shouldYield,La=o.unstable_requestPaint,Ra=o.unstable_now,Pa=o.unstable_getCurrentPriorityLevel,Na=o.unstable_ImmediatePriority,Oa=o.unstable_UserBlockingPriority,Ia=o.unstable_NormalPriority,Da=o.unstable_LowPriority,Ma=o.unstable_IdlePriority,Fa={},ja=void 0!==La?La:function(){},Ba=null,za=null,Ua=!1,$a=Ra(),qa=1e4>$a?Ra:function(){return Ra()-$a};function Ga(){switch(Pa()){case Na:return 99;case Oa:return 98;case Ia:return 97;case Da:return 96;case Ma:return 95;default:throw Error(i(332))}}function Ha(e){switch(e){case 99:return Na;case 98:return Oa;case 97:return Ia;case 96:return Da;case 95:return Ma;default:throw Error(i(332))}}function Za(e,t){return e=Ha(e),Ca(e,t)}function Va(e,t,n){return e=Ha(e),_a(e,t,n)}function Wa(){if(null!==za){var e=za;za=null,Ta(e)}Ya()}function Ya(){if(!Ua&&null!==Ba){Ua=!0;var e=0;try{var t=Ba;Za(99,(function(){for(;e<t.length;e++){var n=t[e];do{n=n(!0)}while(null!==n)}})),Ba=null}catch(n){throw null!==Ba&&(Ba=Ba.slice(e+1)),_a(Na,Wa),n}finally{Ua=!1}}}var Ka=k.ReactCurrentBatchConfig;function Qa(e,t){if(e&&e.defaultProps){for(var n in t=a({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}var Xa=ua(null),Ja=null,eo=null,to=null;function no(){to=eo=Ja=null}function ro(e){var t=Xa.current;ca(Xa),e.type._context._currentValue=t}function ao(e,t){for(;null!==e;){var n=e.alternate;if((e.childLanes&t)===t){if(null===n||(n.childLanes&t)===t)break;n.childLanes|=t}else e.childLanes|=t,null!==n&&(n.childLanes|=t);e=e.return}}function oo(e,t){Ja=e,to=eo=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(Fi=!0),e.firstContext=null)}function io(e,t){if(to!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(to=e,t=1073741823),t={context:e,observedBits:t,next:null},null===eo){if(null===Ja)throw Error(i(308));eo=t,Ja.dependencies={lanes:0,firstContext:t,responders:null}}else eo=eo.next=t;return e._currentValue}var lo=!1;function so(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function uo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function co(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function po(e,t){if(null!==(e=e.updateQueue)){var n=(e=e.shared).pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}}function fo(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var a=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?a=o=i:o=o.next=i,n=n.next}while(null!==n);null===o?a=o=t:o=o.next=t}else a=o=t;return n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:o,shared:r.shared,effects:r.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function mo(e,t,n,r){var o=e.updateQueue;lo=!1;var i=o.firstBaseUpdate,l=o.lastBaseUpdate,s=o.shared.pending;if(null!==s){o.shared.pending=null;var u=s,c=u.next;u.next=null,null===l?i=c:l.next=c,l=u;var d=e.alternate;if(null!==d){var p=(d=d.updateQueue).lastBaseUpdate;p!==l&&(null===p?d.firstBaseUpdate=c:p.next=c,d.lastBaseUpdate=u)}}if(null!==i){for(p=o.baseState,l=0,d=c=u=null;;){s=i.lane;var f=i.eventTime;if((r&s)===s){null!==d&&(d=d.next={eventTime:f,lane:0,tag:i.tag,payload:i.payload,callback:i.callback,next:null});e:{var m=e,g=i;switch(s=t,f=n,g.tag){case 1:if("function"==typeof(m=g.payload)){p=m.call(f,p,s);break e}p=m;break e;case 3:m.flags=-4097&m.flags|64;case 0:if(null==(s="function"==typeof(m=g.payload)?m.call(f,p,s):m))break e;p=a({},p,s);break e;case 2:lo=!0}}null!==i.callback&&(e.flags|=32,null===(s=o.effects)?o.effects=[i]:s.push(i))}else f={eventTime:f,lane:s,tag:i.tag,payload:i.payload,callback:i.callback,next:null},null===d?(c=d=f,u=p):d=d.next=f,l|=s;if(null===(i=i.next)){if(null===(s=o.shared.pending))break;i=s.next,s.next=null,o.lastBaseUpdate=s,o.shared.pending=null}}null===d&&(u=p),o.baseState=u,o.firstBaseUpdate=c,o.lastBaseUpdate=d,Ul|=l,e.lanes=l,e.memoizedState=p}}function go(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],a=r.callback;if(null!==a){if(r.callback=null,r=n,"function"!=typeof a)throw Error(i(191,a));a.call(r)}}}var ho=(new r.Component).refs;function vo(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:a({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var bo={isMounted:function(e){return!!(e=e._reactInternals)&&Ke(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=ps(),a=fs(e),o=co(r,a);o.payload=t,null!=n&&(o.callback=n),po(e,o),ms(e,a,r)},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=ps(),a=fs(e),o=co(r,a);o.tag=1,o.payload=t,null!=n&&(o.callback=n),po(e,o),ms(e,a,r)},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=ps(),r=fs(e),a=co(n,r);a.tag=2,null!=t&&(a.callback=t),po(e,a),ms(e,r,n)}};function yo(e,t,n,r,a,o,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,o,i):!t.prototype||!t.prototype.isPureReactComponent||(!pr(n,r)||!pr(a,o))}function wo(e,t,n){var r=!1,a=pa,o=t.contextType;return"object"==typeof o&&null!==o?o=io(o):(a=va(t)?ga:fa.current,o=(r=null!=(r=t.contextTypes))?ha(e,a):pa),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=bo,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=a,e.__reactInternalMemoizedMaskedChildContext=o),t}function ko(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&bo.enqueueReplaceState(t,t.state,null)}function Eo(e,t,n,r){var a=e.stateNode;a.props=n,a.state=e.memoizedState,a.refs=ho,so(e);var o=t.contextType;"object"==typeof o&&null!==o?a.context=io(o):(o=va(t)?ga:fa.current,a.context=ha(e,o)),mo(e,n,a,r),a.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&(vo(e,t,o,n),a.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof a.getSnapshotBeforeUpdate||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||(t=a.state,"function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount(),t!==a.state&&bo.enqueueReplaceState(a,a.state,null),mo(e,n,a,r),a.state=e.memoizedState),"function"==typeof a.componentDidMount&&(e.flags|=4)}var So=Array.isArray;function xo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(i(309));var r=n.stateNode}if(!r)throw Error(i(147,e));var a=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===a?t.ref:(t=function(e){var t=r.refs;t===ho&&(t=r.refs={}),null===e?delete t[a]:t[a]=e},t._stringRef=a,t)}if("string"!=typeof e)throw Error(i(284));if(!n._owner)throw Error(i(290,e))}return e}function Co(e,t){if("textarea"!==e.type)throw Error(i(31,"[object Object]"===Object.prototype.toString.call(t)?"object with keys {"+Object.keys(t).join(", ")+"}":t))}function _o(e){function t(t,n){if(e){var r=t.lastEffect;null!==r?(r.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.flags=8}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function a(e,t){return(e=Zs(e,t)).index=0,e.sibling=null,e}function o(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.flags=2,n):r:(t.flags=2,n):n}function l(t){return e&&null===t.alternate&&(t.flags=2),t}function s(e,t,n,r){return null===t||6!==t.tag?((t=Ks(n,e.mode,r)).return=e,t):((t=a(t,n)).return=e,t)}function u(e,t,n,r){return null!==t&&t.elementType===n.type?((r=a(t,n.props)).ref=xo(e,t,n),r.return=e,r):((r=Vs(n.type,n.key,n.props,null,e.mode,r)).ref=xo(e,t,n),r.return=e,r)}function c(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Qs(n,e.mode,r)).return=e,t):((t=a(t,n.children||[])).return=e,t)}function d(e,t,n,r,o){return null===t||7!==t.tag?((t=Ws(n,e.mode,r,o)).return=e,t):((t=a(t,n)).return=e,t)}function p(e,t,n){if("string"==typeof t||"number"==typeof t)return(t=Ks(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case E:return(n=Vs(t.type,t.key,t.props,null,e.mode,n)).ref=xo(e,null,t),n.return=e,n;case S:return(t=Qs(t,e.mode,n)).return=e,t}if(So(t)||$(t))return(t=Ws(t,e.mode,n,null)).return=e,t;Co(e,t)}return null}function f(e,t,n,r){var a=null!==t?t.key:null;if("string"==typeof n||"number"==typeof n)return null!==a?null:s(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case E:return n.key===a?n.type===x?d(e,t,n.props.children,r,a):u(e,t,n,r):null;case S:return n.key===a?c(e,t,n,r):null}if(So(n)||$(n))return null!==a?null:d(e,t,n,r,null);Co(e,n)}return null}function m(e,t,n,r,a){if("string"==typeof r||"number"==typeof r)return s(t,e=e.get(n)||null,""+r,a);if("object"==typeof r&&null!==r){switch(r.$$typeof){case E:return e=e.get(null===r.key?n:r.key)||null,r.type===x?d(t,e,r.props.children,a,r.key):u(t,e,r,a);case S:return c(t,e=e.get(null===r.key?n:r.key)||null,r,a)}if(So(r)||$(r))return d(t,e=e.get(n)||null,r,a,null);Co(t,r)}return null}function g(a,i,l,s){for(var u=null,c=null,d=i,g=i=0,h=null;null!==d&&g<l.length;g++){d.index>g?(h=d,d=null):h=d.sibling;var v=f(a,d,l[g],s);if(null===v){null===d&&(d=h);break}e&&d&&null===v.alternate&&t(a,d),i=o(v,i,g),null===c?u=v:c.sibling=v,c=v,d=h}if(g===l.length)return n(a,d),u;if(null===d){for(;g<l.length;g++)null!==(d=p(a,l[g],s))&&(i=o(d,i,g),null===c?u=d:c.sibling=d,c=d);return u}for(d=r(a,d);g<l.length;g++)null!==(h=m(d,a,g,l[g],s))&&(e&&null!==h.alternate&&d.delete(null===h.key?g:h.key),i=o(h,i,g),null===c?u=h:c.sibling=h,c=h);return e&&d.forEach((function(e){return t(a,e)})),u}function h(a,l,s,u){var c=$(s);if("function"!=typeof c)throw Error(i(150));if(null==(s=c.call(s)))throw Error(i(151));for(var d=c=null,g=l,h=l=0,v=null,b=s.next();null!==g&&!b.done;h++,b=s.next()){g.index>h?(v=g,g=null):v=g.sibling;var y=f(a,g,b.value,u);if(null===y){null===g&&(g=v);break}e&&g&&null===y.alternate&&t(a,g),l=o(y,l,h),null===d?c=y:d.sibling=y,d=y,g=v}if(b.done)return n(a,g),c;if(null===g){for(;!b.done;h++,b=s.next())null!==(b=p(a,b.value,u))&&(l=o(b,l,h),null===d?c=b:d.sibling=b,d=b);return c}for(g=r(a,g);!b.done;h++,b=s.next())null!==(b=m(g,a,h,b.value,u))&&(e&&null!==b.alternate&&g.delete(null===b.key?h:b.key),l=o(b,l,h),null===d?c=b:d.sibling=b,d=b);return e&&g.forEach((function(e){return t(a,e)})),c}return function(e,r,o,s){var u="object"==typeof o&&null!==o&&o.type===x&&null===o.key;u&&(o=o.props.children);var c="object"==typeof o&&null!==o;if(c)switch(o.$$typeof){case E:e:{for(c=o.key,u=r;null!==u;){if(u.key===c){if(7===u.tag){if(o.type===x){n(e,u.sibling),(r=a(u,o.props.children)).return=e,e=r;break e}}else if(u.elementType===o.type){n(e,u.sibling),(r=a(u,o.props)).ref=xo(e,u,o),r.return=e,e=r;break e}n(e,u);break}t(e,u),u=u.sibling}o.type===x?((r=Ws(o.props.children,e.mode,s,o.key)).return=e,e=r):((s=Vs(o.type,o.key,o.props,null,e.mode,s)).ref=xo(e,r,o),s.return=e,e=s)}return l(e);case S:e:{for(u=o.key;null!==r;){if(r.key===u){if(4===r.tag&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),(r=a(r,o.children||[])).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=Qs(o,e.mode,s)).return=e,e=r}return l(e)}if("string"==typeof o||"number"==typeof o)return o=""+o,null!==r&&6===r.tag?(n(e,r.sibling),(r=a(r,o)).return=e,e=r):(n(e,r),(r=Ks(o,e.mode,s)).return=e,e=r),l(e);if(So(o))return g(e,r,o,s);if($(o))return h(e,r,o,s);if(c&&Co(e,o),void 0===o&&!u)switch(e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(i(152,V(e.type)||"Component"))}return n(e,r)}}var To=_o(!0),Ao=_o(!1),Lo={},Ro=ua(Lo),Po=ua(Lo),No=ua(Lo);function Oo(e){if(e===Lo)throw Error(i(174));return e}function Io(e,t){switch(da(No,t),da(Po,e),da(Ro,Lo),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:me(null,"");break;default:t=me(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}ca(Ro),da(Ro,t)}function Do(){ca(Ro),ca(Po),ca(No)}function Mo(e){Oo(No.current);var t=Oo(Ro.current),n=me(t,e.type);t!==n&&(da(Po,e),da(Ro,n))}function Fo(e){Po.current===e&&(ca(Ro),ca(Po))}var jo=ua(0);function Bo(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var zo=null,Uo=null,$o=!1;function qo(e,t){var n=Gs(5,null,null,0);n.elementType="DELETED",n.type="DELETED",n.stateNode=t,n.return=e,n.flags=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Go(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function Ho(e){if($o){var t=Uo;if(t){var n=t;if(!Go(e,t)){if(!(t=Wr(n.nextSibling))||!Go(e,t))return e.flags=-1025&e.flags|2,$o=!1,void(zo=e);qo(zo,n)}zo=e,Uo=Wr(t.firstChild)}else e.flags=-1025&e.flags|2,$o=!1,zo=e}}function Zo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;zo=e}function Vo(e){if(e!==zo)return!1;if(!$o)return Zo(e),$o=!0,!1;var t=e.type;if(5!==e.tag||"head"!==t&&"body"!==t&&!Gr(t,e.memoizedProps))for(t=Uo;t;)qo(e,t),t=Wr(t.nextSibling);if(Zo(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(i(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){Uo=Wr(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}Uo=null}}else Uo=zo?Wr(e.stateNode.nextSibling):null;return!0}function Wo(){Uo=zo=null,$o=!1}var Yo=[];function Ko(){for(var e=0;e<Yo.length;e++)Yo[e]._workInProgressVersionPrimary=null;Yo.length=0}var Qo=k.ReactCurrentDispatcher,Xo=k.ReactCurrentBatchConfig,Jo=0,ei=null,ti=null,ni=null,ri=!1,ai=!1;function oi(){throw Error(i(321))}function ii(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!cr(e[n],t[n]))return!1;return!0}function li(e,t,n,r,a,o){if(Jo=o,ei=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Qo.current=null===e||null===e.memoizedState?Oi:Ii,e=n(r,a),ai){o=0;do{if(ai=!1,!(25>o))throw Error(i(301));o+=1,ni=ti=null,t.updateQueue=null,Qo.current=Di,e=n(r,a)}while(ai)}if(Qo.current=Ni,t=null!==ti&&null!==ti.next,Jo=0,ni=ti=ei=null,ri=!1,t)throw Error(i(300));return e}function si(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===ni?ei.memoizedState=ni=e:ni=ni.next=e,ni}function ui(){if(null===ti){var e=ei.alternate;e=null!==e?e.memoizedState:null}else e=ti.next;var t=null===ni?ei.memoizedState:ni.next;if(null!==t)ni=t,ti=e;else{if(null===e)throw Error(i(310));e={memoizedState:(ti=e).memoizedState,baseState:ti.baseState,baseQueue:ti.baseQueue,queue:ti.queue,next:null},null===ni?ei.memoizedState=ni=e:ni=ni.next=e}return ni}function ci(e,t){return"function"==typeof t?t(e):t}function di(e){var t=ui(),n=t.queue;if(null===n)throw Error(i(311));n.lastRenderedReducer=e;var r=ti,a=r.baseQueue,o=n.pending;if(null!==o){if(null!==a){var l=a.next;a.next=o.next,o.next=l}r.baseQueue=a=o,n.pending=null}if(null!==a){a=a.next,r=r.baseState;var s=l=o=null,u=a;do{var c=u.lane;if((Jo&c)===c)null!==s&&(s=s.next={lane:0,action:u.action,eagerReducer:u.eagerReducer,eagerState:u.eagerState,next:null}),r=u.eagerReducer===e?u.eagerState:e(r,u.action);else{var d={lane:c,action:u.action,eagerReducer:u.eagerReducer,eagerState:u.eagerState,next:null};null===s?(l=s=d,o=r):s=s.next=d,ei.lanes|=c,Ul|=c}u=u.next}while(null!==u&&u!==a);null===s?o=r:s.next=l,cr(r,t.memoizedState)||(Fi=!0),t.memoizedState=r,t.baseState=o,t.baseQueue=s,n.lastRenderedState=r}return[t.memoizedState,n.dispatch]}function pi(e){var t=ui(),n=t.queue;if(null===n)throw Error(i(311));n.lastRenderedReducer=e;var r=n.dispatch,a=n.pending,o=t.memoizedState;if(null!==a){n.pending=null;var l=a=a.next;do{o=e(o,l.action),l=l.next}while(l!==a);cr(o,t.memoizedState)||(Fi=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,r]}function fi(e,t,n){var r=t._getVersion;r=r(t._source);var a=t._workInProgressVersionPrimary;if(null!==a?e=a===r:(e=e.mutableReadLanes,(e=(Jo&e)===e)&&(t._workInProgressVersionPrimary=r,Yo.push(t))),e)return n(t._source);throw Yo.push(t),Error(i(350))}function mi(e,t,n,r){var a=Ol;if(null===a)throw Error(i(349));var o=t._getVersion,l=o(t._source),s=Qo.current,u=s.useState((function(){return fi(a,t,n)})),c=u[1],d=u[0];u=ni;var p=e.memoizedState,f=p.refs,m=f.getSnapshot,g=p.source;p=p.subscribe;var h=ei;return e.memoizedState={refs:f,source:t,subscribe:r},s.useEffect((function(){f.getSnapshot=n,f.setSnapshot=c;var e=o(t._source);if(!cr(l,e)){e=n(t._source),cr(d,e)||(c(e),e=fs(h),a.mutableReadLanes|=e&a.pendingLanes),e=a.mutableReadLanes,a.entangledLanes|=e;for(var r=a.entanglements,i=e;0<i;){var s=31-Gt(i),u=1<<s;r[s]|=e,i&=~u}}}),[n,t,r]),s.useEffect((function(){return r(t._source,(function(){var e=f.getSnapshot,n=f.setSnapshot;try{n(e(t._source));var r=fs(h);a.mutableReadLanes|=r&a.pendingLanes}catch(o){n((function(){throw o}))}}))}),[t,r]),cr(m,n)&&cr(g,t)&&cr(p,r)||((e={pending:null,dispatch:null,lastRenderedReducer:ci,lastRenderedState:d}).dispatch=c=Pi.bind(null,ei,e),u.queue=e,u.baseQueue=null,d=fi(a,t,n),u.memoizedState=u.baseState=d),d}function gi(e,t,n){return mi(ui(),e,t,n)}function hi(e){var t=si();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={pending:null,dispatch:null,lastRenderedReducer:ci,lastRenderedState:e}).dispatch=Pi.bind(null,ei,e),[t.memoizedState,e]}function vi(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=ei.updateQueue)?(t={lastEffect:null},ei.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function bi(e){return e={current:e},si().memoizedState=e}function yi(){return ui().memoizedState}function wi(e,t,n,r){var a=si();ei.flags|=e,a.memoizedState=vi(1|t,n,void 0,void 0===r?null:r)}function ki(e,t,n,r){var a=ui();r=void 0===r?null:r;var o=void 0;if(null!==ti){var i=ti.memoizedState;if(o=i.destroy,null!==r&&ii(r,i.deps))return void vi(t,n,o,r)}ei.flags|=e,a.memoizedState=vi(1|t,n,o,r)}function Ei(e,t){return wi(516,4,e,t)}function Si(e,t){return ki(516,4,e,t)}function xi(e,t){return ki(4,2,e,t)}function Ci(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function _i(e,t,n){return n=null!=n?n.concat([e]):null,ki(4,2,Ci.bind(null,t,e),n)}function Ti(){}function Ai(e,t){var n=ui();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&ii(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function Li(e,t){var n=ui();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&ii(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function Ri(e,t){var n=Ga();Za(98>n?98:n,(function(){e(!0)})),Za(97<n?97:n,(function(){var n=Xo.transition;Xo.transition=1;try{e(!1),t()}finally{Xo.transition=n}}))}function Pi(e,t,n){var r=ps(),a=fs(e),o={lane:a,action:n,eagerReducer:null,eagerState:null,next:null},i=t.pending;if(null===i?o.next=o:(o.next=i.next,i.next=o),t.pending=o,i=e.alternate,e===ei||null!==i&&i===ei)ai=ri=!0;else{if(0===e.lanes&&(null===i||0===i.lanes)&&null!==(i=t.lastRenderedReducer))try{var l=t.lastRenderedState,s=i(l,n);if(o.eagerReducer=i,o.eagerState=s,cr(s,l))return}catch(u){}ms(e,a,r)}}var Ni={readContext:io,useCallback:oi,useContext:oi,useEffect:oi,useImperativeHandle:oi,useLayoutEffect:oi,useMemo:oi,useReducer:oi,useRef:oi,useState:oi,useDebugValue:oi,useDeferredValue:oi,useTransition:oi,useMutableSource:oi,useOpaqueIdentifier:oi,unstable_isNewReconciler:!1},Oi={readContext:io,useCallback:function(e,t){return si().memoizedState=[e,void 0===t?null:t],e},useContext:io,useEffect:Ei,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,wi(4,2,Ci.bind(null,t,e),n)},useLayoutEffect:function(e,t){return wi(4,2,e,t)},useMemo:function(e,t){var n=si();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=si();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e=(e=r.queue={pending:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=Pi.bind(null,ei,e),[r.memoizedState,e]},useRef:bi,useState:hi,useDebugValue:Ti,useDeferredValue:function(e){var t=hi(e),n=t[0],r=t[1];return Ei((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=hi(!1),t=e[0];return bi(e=Ri.bind(null,e[1])),[e,t]},useMutableSource:function(e,t,n){var r=si();return r.memoizedState={refs:{getSnapshot:t,setSnapshot:null},source:e,subscribe:n},mi(r,e,t,n)},useOpaqueIdentifier:function(){if($o){var e=!1,t=function(e){return{$$typeof:D,toString:e,valueOf:e}}((function(){throw e||(e=!0,n("r:"+(Kr++).toString(36))),Error(i(355))})),n=hi(t)[1];return 0==(2&ei.mode)&&(ei.flags|=516,vi(5,(function(){n("r:"+(Kr++).toString(36))}),void 0,null)),t}return hi(t="r:"+(Kr++).toString(36)),t},unstable_isNewReconciler:!1},Ii={readContext:io,useCallback:Ai,useContext:io,useEffect:Si,useImperativeHandle:_i,useLayoutEffect:xi,useMemo:Li,useReducer:di,useRef:yi,useState:function(){return di(ci)},useDebugValue:Ti,useDeferredValue:function(e){var t=di(ci),n=t[0],r=t[1];return Si((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=di(ci)[0];return[yi().current,e]},useMutableSource:gi,useOpaqueIdentifier:function(){return di(ci)[0]},unstable_isNewReconciler:!1},Di={readContext:io,useCallback:Ai,useContext:io,useEffect:Si,useImperativeHandle:_i,useLayoutEffect:xi,useMemo:Li,useReducer:pi,useRef:yi,useState:function(){return pi(ci)},useDebugValue:Ti,useDeferredValue:function(e){var t=pi(ci),n=t[0],r=t[1];return Si((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=pi(ci)[0];return[yi().current,e]},useMutableSource:gi,useOpaqueIdentifier:function(){return pi(ci)[0]},unstable_isNewReconciler:!1},Mi=k.ReactCurrentOwner,Fi=!1;function ji(e,t,n,r){t.child=null===e?Ao(t,null,n,r):To(t,e.child,n,r)}function Bi(e,t,n,r,a){n=n.render;var o=t.ref;return oo(t,a),r=li(e,t,n,r,o,a),null===e||Fi?(t.flags|=1,ji(e,t,r,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~a,ol(e,t,a))}function zi(e,t,n,r,a,o){if(null===e){var i=n.type;return"function"!=typeof i||Hs(i)||void 0!==i.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Vs(n.type,null,r,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=i,Ui(e,t,i,r,a,o))}return i=e.child,0==(a&o)&&(a=i.memoizedProps,(n=null!==(n=n.compare)?n:pr)(a,r)&&e.ref===t.ref)?ol(e,t,o):(t.flags|=1,(e=Zs(i,r)).ref=t.ref,e.return=t,t.child=e)}function Ui(e,t,n,r,a,o){if(null!==e&&pr(e.memoizedProps,r)&&e.ref===t.ref){if(Fi=!1,0==(o&a))return t.lanes=e.lanes,ol(e,t,o);0!=(16384&e.flags)&&(Fi=!0)}return Gi(e,t,n,r,o)}function $i(e,t,n){var r=t.pendingProps,a=r.children,o=null!==e?e.memoizedState:null;if("hidden"===r.mode||"unstable-defer-without-hiding"===r.mode)if(0==(4&t.mode))t.memoizedState={baseLanes:0},Es(t,n);else{if(0==(1073741824&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e},Es(t,e),null;t.memoizedState={baseLanes:0},Es(t,null!==o?o.baseLanes:n)}else null!==o?(r=o.baseLanes|n,t.memoizedState=null):r=n,Es(t,r);return ji(e,t,a,n),t.child}function qi(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=128)}function Gi(e,t,n,r,a){var o=va(n)?ga:fa.current;return o=ha(t,o),oo(t,a),n=li(e,t,n,r,o,a),null===e||Fi?(t.flags|=1,ji(e,t,n,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~a,ol(e,t,a))}function Hi(e,t,n,r,a){if(va(n)){var o=!0;ka(t)}else o=!1;if(oo(t,a),null===t.stateNode)null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),wo(t,n,r),Eo(t,n,r,a),r=!0;else if(null===e){var i=t.stateNode,l=t.memoizedProps;i.props=l;var s=i.context,u=n.contextType;"object"==typeof u&&null!==u?u=io(u):u=ha(t,u=va(n)?ga:fa.current);var c=n.getDerivedStateFromProps,d="function"==typeof c||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(l!==r||s!==u)&&ko(t,i,r,u),lo=!1;var p=t.memoizedState;i.state=p,mo(t,r,i,a),s=t.memoizedState,l!==r||p!==s||ma.current||lo?("function"==typeof c&&(vo(t,n,c,r),s=t.memoizedState),(l=lo||yo(t,n,l,r,p,s,u))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4)):("function"==typeof i.componentDidMount&&(t.flags|=4),t.memoizedProps=r,t.memoizedState=s),i.props=r,i.state=s,i.context=u,r=l):("function"==typeof i.componentDidMount&&(t.flags|=4),r=!1)}else{i=t.stateNode,uo(e,t),l=t.memoizedProps,u=t.type===t.elementType?l:Qa(t.type,l),i.props=u,d=t.pendingProps,p=i.context,"object"==typeof(s=n.contextType)&&null!==s?s=io(s):s=ha(t,s=va(n)?ga:fa.current);var f=n.getDerivedStateFromProps;(c="function"==typeof f||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(l!==d||p!==s)&&ko(t,i,r,s),lo=!1,p=t.memoizedState,i.state=p,mo(t,r,i,a);var m=t.memoizedState;l!==d||p!==m||ma.current||lo?("function"==typeof f&&(vo(t,n,f,r),m=t.memoizedState),(u=lo||yo(t,n,u,r,p,m,s))?(c||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,m,s),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,m,s)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=256)):("function"!=typeof i.componentDidUpdate||l===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||l===e.memoizedProps&&p===e.memoizedState||(t.flags|=256),t.memoizedProps=r,t.memoizedState=m),i.props=r,i.state=m,i.context=s,r=u):("function"!=typeof i.componentDidUpdate||l===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||l===e.memoizedProps&&p===e.memoizedState||(t.flags|=256),r=!1)}return Zi(e,t,n,r,o,a)}function Zi(e,t,n,r,a,o){qi(e,t);var i=0!=(64&t.flags);if(!r&&!i)return a&&Ea(t,n,!1),ol(e,t,o);r=t.stateNode,Mi.current=t;var l=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=To(t,e.child,null,o),t.child=To(t,null,l,o)):ji(e,t,l,o),t.memoizedState=r.state,a&&Ea(t,n,!0),t.child}function Vi(e){var t=e.stateNode;t.pendingContext?ya(0,t.pendingContext,t.pendingContext!==t.context):t.context&&ya(0,t.context,!1),Io(e,t.containerInfo)}var Wi,Yi,Ki,Qi={dehydrated:null,retryLane:0};function Xi(e,t,n){var r,a=t.pendingProps,o=jo.current,i=!1;return(r=0!=(64&t.flags))||(r=(null===e||null!==e.memoizedState)&&0!=(2&o)),r?(i=!0,t.flags&=-65):null!==e&&null===e.memoizedState||void 0===a.fallback||!0===a.unstable_avoidThisFallback||(o|=1),da(jo,1&o),null===e?(void 0!==a.fallback&&Ho(t),e=a.children,o=a.fallback,i?(e=Ji(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qi,e):"number"==typeof a.unstable_expectedLoadTime?(e=Ji(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qi,t.lanes=33554432,e):((n=Ys({mode:"visible",children:e},t.mode,n,null)).return=t,t.child=n)):(e.memoizedState,i?(a=tl(e,t,a.children,a.fallback,n),i=t.child,o=e.child.memoizedState,i.memoizedState=null===o?{baseLanes:n}:{baseLanes:o.baseLanes|n},i.childLanes=e.childLanes&~n,t.memoizedState=Qi,a):(n=el(e,t,a.children,n),t.memoizedState=null,n))}function Ji(e,t,n,r){var a=e.mode,o=e.child;return t={mode:"hidden",children:t},0==(2&a)&&null!==o?(o.childLanes=0,o.pendingProps=t):o=Ys(t,a,0,null),n=Ws(n,a,r,null),o.return=e,n.return=e,o.sibling=n,e.child=o,n}function el(e,t,n,r){var a=e.child;return e=a.sibling,n=Zs(a,{mode:"visible",children:n}),0==(2&t.mode)&&(n.lanes=r),n.return=t,n.sibling=null,null!==e&&(e.nextEffect=null,e.flags=8,t.firstEffect=t.lastEffect=e),t.child=n}function tl(e,t,n,r,a){var o=t.mode,i=e.child;e=i.sibling;var l={mode:"hidden",children:n};return 0==(2&o)&&t.child!==i?((n=t.child).childLanes=0,n.pendingProps=l,null!==(i=n.lastEffect)?(t.firstEffect=n.firstEffect,t.lastEffect=i,i.nextEffect=null):t.firstEffect=t.lastEffect=null):n=Zs(i,l),null!==e?r=Zs(e,r):(r=Ws(r,o,a,null)).flags|=2,r.return=t,n.return=t,n.sibling=r,t.child=n,r}function nl(e,t){e.lanes|=t;var n=e.alternate;null!==n&&(n.lanes|=t),ao(e.return,t)}function rl(e,t,n,r,a,o){var i=e.memoizedState;null===i?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:a,lastEffect:o}:(i.isBackwards=t,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=n,i.tailMode=a,i.lastEffect=o)}function al(e,t,n){var r=t.pendingProps,a=r.revealOrder,o=r.tail;if(ji(e,t,r.children,n),0!=(2&(r=jo.current)))r=1&r|2,t.flags|=64;else{if(null!==e&&0!=(64&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&nl(e,n);else if(19===e.tag)nl(e,n);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(da(jo,r),0==(2&t.mode))t.memoizedState=null;else switch(a){case"forwards":for(n=t.child,a=null;null!==n;)null!==(e=n.alternate)&&null===Bo(e)&&(a=n),n=n.sibling;null===(n=a)?(a=t.child,t.child=null):(a=n.sibling,n.sibling=null),rl(t,!1,a,n,o,t.lastEffect);break;case"backwards":for(n=null,a=t.child,t.child=null;null!==a;){if(null!==(e=a.alternate)&&null===Bo(e)){t.child=a;break}e=a.sibling,a.sibling=n,n=a,a=e}rl(t,!0,n,null,o,t.lastEffect);break;case"together":rl(t,!1,null,null,void 0,t.lastEffect);break;default:t.memoizedState=null}return t.child}function ol(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Ul|=t.lanes,0!=(n&t.childLanes)){if(null!==e&&t.child!==e.child)throw Error(i(153));if(null!==t.child){for(n=Zs(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Zs(e,e.pendingProps)).return=t;n.sibling=null}return t.child}return null}function il(e,t){if(!$o)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function ll(e,t,n){var r=t.pendingProps;switch(t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:case 17:return va(t.type)&&ba(),null;case 3:return Do(),ca(ma),ca(fa),Ko(),(r=t.stateNode).pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(Vo(t)?t.flags|=4:r.hydrate||(t.flags|=256)),null;case 5:Fo(t);var o=Oo(No.current);if(n=t.type,null!==e&&null!=t.stateNode)Yi(e,t,n,r),e.ref!==t.ref&&(t.flags|=128);else{if(!r){if(null===t.stateNode)throw Error(i(166));return null}if(e=Oo(Ro.current),Vo(t)){r=t.stateNode,n=t.type;var l=t.memoizedProps;switch(r[Xr]=t,r[Jr]=l,n){case"dialog":Rr("cancel",r),Rr("close",r);break;case"iframe":case"object":case"embed":Rr("load",r);break;case"video":case"audio":for(e=0;e<_r.length;e++)Rr(_r[e],r);break;case"source":Rr("error",r);break;case"img":case"image":case"link":Rr("error",r),Rr("load",r);break;case"details":Rr("toggle",r);break;case"input":ee(r,l),Rr("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!l.multiple},Rr("invalid",r);break;case"textarea":se(r,l),Rr("invalid",r)}for(var u in xe(n,l),e=null,l)l.hasOwnProperty(u)&&(o=l[u],"children"===u?"string"==typeof o?r.textContent!==o&&(e=["children",o]):"number"==typeof o&&r.textContent!==""+o&&(e=["children",""+o]):s.hasOwnProperty(u)&&null!=o&&"onScroll"===u&&Rr("scroll",r));switch(n){case"input":K(r),re(r,l,!0);break;case"textarea":K(r),ce(r);break;case"select":case"option":break;default:"function"==typeof l.onClick&&(r.onclick=zr)}r=e,t.updateQueue=r,null!==r&&(t.flags|=4)}else{switch(u=9===o.nodeType?o:o.ownerDocument,e===de&&(e=fe(n)),e===de?"script"===n?((e=u.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=u.createElement(n,{is:r.is}):(e=u.createElement(n),"select"===n&&(u=e,r.multiple?u.multiple=!0:r.size&&(u.size=r.size))):e=u.createElementNS(e,n),e[Xr]=t,e[Jr]=r,Wi(e,t),t.stateNode=e,u=Ce(n,r),n){case"dialog":Rr("cancel",e),Rr("close",e),o=r;break;case"iframe":case"object":case"embed":Rr("load",e),o=r;break;case"video":case"audio":for(o=0;o<_r.length;o++)Rr(_r[o],e);o=r;break;case"source":Rr("error",e),o=r;break;case"img":case"image":case"link":Rr("error",e),Rr("load",e),o=r;break;case"details":Rr("toggle",e),o=r;break;case"input":ee(e,r),o=J(e,r),Rr("invalid",e);break;case"option":o=oe(e,r);break;case"select":e._wrapperState={wasMultiple:!!r.multiple},o=a({},r,{value:void 0}),Rr("invalid",e);break;case"textarea":se(e,r),o=le(e,r),Rr("invalid",e);break;default:o=r}xe(n,o);var c=o;for(l in c)if(c.hasOwnProperty(l)){var d=c[l];"style"===l?Ee(e,d):"dangerouslySetInnerHTML"===l?null!=(d=d?d.__html:void 0)&&ve(e,d):"children"===l?"string"==typeof d?("textarea"!==n||""!==d)&&be(e,d):"number"==typeof d&&be(e,""+d):"suppressContentEditableWarning"!==l&&"suppressHydrationWarning"!==l&&"autoFocus"!==l&&(s.hasOwnProperty(l)?null!=d&&"onScroll"===l&&Rr("scroll",e):null!=d&&w(e,l,d,u))}switch(n){case"input":K(e),re(e,r,!1);break;case"textarea":K(e),ce(e);break;case"option":null!=r.value&&e.setAttribute("value",""+W(r.value));break;case"select":e.multiple=!!r.multiple,null!=(l=r.value)?ie(e,!!r.multiple,l,!1):null!=r.defaultValue&&ie(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=zr)}qr(n,r)&&(t.flags|=4)}null!==t.ref&&(t.flags|=128)}return null;case 6:if(e&&null!=t.stateNode)Ki(0,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(i(166));n=Oo(No.current),Oo(Ro.current),Vo(t)?(r=t.stateNode,n=t.memoizedProps,r[Xr]=t,r.nodeValue!==n&&(t.flags|=4)):((r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[Xr]=t,t.stateNode=r)}return null;case 13:return ca(jo),r=t.memoizedState,0!=(64&t.flags)?(t.lanes=n,t):(r=null!==r,n=!1,null===e?void 0!==t.memoizedProps.fallback&&Vo(t):n=null!==e.memoizedState,r&&!n&&0!=(2&t.mode)&&(null===e&&!0!==t.memoizedProps.unstable_avoidThisFallback||0!=(1&jo.current)?0===jl&&(jl=3):(0!==jl&&3!==jl||(jl=4),null===Ol||0==(134217727&Ul)&&0==(134217727&$l)||bs(Ol,Dl))),(r||n)&&(t.flags|=4),null);case 4:return Do(),null===e&&Nr(t.stateNode.containerInfo),null;case 10:return ro(t),null;case 19:if(ca(jo),null===(r=t.memoizedState))return null;if(l=0!=(64&t.flags),null===(u=r.rendering))if(l)il(r,!1);else{if(0!==jl||null!==e&&0!=(64&e.flags))for(e=t.child;null!==e;){if(null!==(u=Bo(e))){for(t.flags|=64,il(r,!1),null!==(l=u.updateQueue)&&(t.updateQueue=l,t.flags|=4),null===r.lastEffect&&(t.firstEffect=null),t.lastEffect=r.lastEffect,r=n,n=t.child;null!==n;)e=r,(l=n).flags&=2,l.nextEffect=null,l.firstEffect=null,l.lastEffect=null,null===(u=l.alternate)?(l.childLanes=0,l.lanes=e,l.child=null,l.memoizedProps=null,l.memoizedState=null,l.updateQueue=null,l.dependencies=null,l.stateNode=null):(l.childLanes=u.childLanes,l.lanes=u.lanes,l.child=u.child,l.memoizedProps=u.memoizedProps,l.memoizedState=u.memoizedState,l.updateQueue=u.updateQueue,l.type=u.type,e=u.dependencies,l.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return da(jo,1&jo.current|2),t.child}e=e.sibling}null!==r.tail&&qa()>Zl&&(t.flags|=64,l=!0,il(r,!1),t.lanes=33554432)}else{if(!l)if(null!==(e=Bo(u))){if(t.flags|=64,l=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),il(r,!0),null===r.tail&&"hidden"===r.tailMode&&!u.alternate&&!$o)return null!==(t=t.lastEffect=r.lastEffect)&&(t.nextEffect=null),null}else 2*qa()-r.renderingStartTime>Zl&&1073741824!==n&&(t.flags|=64,l=!0,il(r,!1),t.lanes=33554432);r.isBackwards?(u.sibling=t.child,t.child=u):(null!==(n=r.last)?n.sibling=u:t.child=u,r.last=u)}return null!==r.tail?(n=r.tail,r.rendering=n,r.tail=n.sibling,r.lastEffect=t.lastEffect,r.renderingStartTime=qa(),n.sibling=null,t=jo.current,da(jo,l?1&t|2:1&t),n):null;case 23:case 24:return Ss(),null!==e&&null!==e.memoizedState!=(null!==t.memoizedState)&&"unstable-defer-without-hiding"!==r.mode&&(t.flags|=4),null}throw Error(i(156,t.tag))}function sl(e){switch(e.tag){case 1:va(e.type)&&ba();var t=e.flags;return 4096&t?(e.flags=-4097&t|64,e):null;case 3:if(Do(),ca(ma),ca(fa),Ko(),0!=(64&(t=e.flags)))throw Error(i(285));return e.flags=-4097&t|64,e;case 5:return Fo(e),null;case 13:return ca(jo),4096&(t=e.flags)?(e.flags=-4097&t|64,e):null;case 19:return ca(jo),null;case 4:return Do(),null;case 10:return ro(e),null;case 23:case 24:return Ss(),null;default:return null}}function ul(e,t){try{var n="",r=t;do{n+=Z(r),r=r.return}while(r);var a=n}catch(o){a="\nError generating stack: "+o.message+"\n"+o.stack}return{value:e,source:t,stack:a}}function cl(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}Wi=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Yi=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,Oo(Ro.current);var i,l=null;switch(n){case"input":o=J(e,o),r=J(e,r),l=[];break;case"option":o=oe(e,o),r=oe(e,r),l=[];break;case"select":o=a({},o,{value:void 0}),r=a({},r,{value:void 0}),l=[];break;case"textarea":o=le(e,o),r=le(e,r),l=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=zr)}for(d in xe(n,r),n=null,o)if(!r.hasOwnProperty(d)&&o.hasOwnProperty(d)&&null!=o[d])if("style"===d){var u=o[d];for(i in u)u.hasOwnProperty(i)&&(n||(n={}),n[i]="")}else"dangerouslySetInnerHTML"!==d&&"children"!==d&&"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&"autoFocus"!==d&&(s.hasOwnProperty(d)?l||(l=[]):(l=l||[]).push(d,null));for(d in r){var c=r[d];if(u=null!=o?o[d]:void 0,r.hasOwnProperty(d)&&c!==u&&(null!=c||null!=u))if("style"===d)if(u){for(i in u)!u.hasOwnProperty(i)||c&&c.hasOwnProperty(i)||(n||(n={}),n[i]="");for(i in c)c.hasOwnProperty(i)&&u[i]!==c[i]&&(n||(n={}),n[i]=c[i])}else n||(l||(l=[]),l.push(d,n)),n=c;else"dangerouslySetInnerHTML"===d?(c=c?c.__html:void 0,u=u?u.__html:void 0,null!=c&&u!==c&&(l=l||[]).push(d,c)):"children"===d?"string"!=typeof c&&"number"!=typeof c||(l=l||[]).push(d,""+c):"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&(s.hasOwnProperty(d)?(null!=c&&"onScroll"===d&&Rr("scroll",e),l||u===c||(l=[])):"object"==typeof c&&null!==c&&c.$$typeof===D?c.toString():(l=l||[]).push(d,c))}n&&(l=l||[]).push("style",n);var d=l;(t.updateQueue=d)&&(t.flags|=4)}},Ki=function(e,t,n,r){n!==r&&(t.flags|=4)};var dl="function"==typeof WeakMap?WeakMap:Map;function pl(e,t,n){(n=co(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Kl||(Kl=!0,Ql=r),cl(0,t)},n}function fl(e,t,n){(n=co(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var a=t.value;n.payload=function(){return cl(0,t),r(a)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){"function"!=typeof r&&(null===Xl?Xl=new Set([this]):Xl.add(this),cl(0,t));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}var ml="function"==typeof WeakSet?WeakSet:Set;function gl(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(n){zs(e,n)}else t.current=null}function hl(e,t){switch(t.tag){case 0:case 11:case 15:case 22:case 5:case 6:case 4:case 17:return;case 1:if(256&t.flags&&null!==e){var n=e.memoizedProps,r=e.memoizedState;t=(e=t.stateNode).getSnapshotBeforeUpdate(t.elementType===t.type?n:Qa(t.type,n),r),e.__reactInternalSnapshotBeforeUpdate=t}return;case 3:return void(256&t.flags&&Vr(t.stateNode.containerInfo))}throw Error(i(163))}function vl(e,t,n){switch(n.tag){case 0:case 11:case 15:case 22:if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{if(3==(3&e.tag)){var r=e.create;e.destroy=r()}e=e.next}while(e!==t)}if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{var a=e;r=a.next,0!=(4&(a=a.tag))&&0!=(1&a)&&(Fs(n,e),Ms(n,e)),e=r}while(e!==t)}return;case 1:return e=n.stateNode,4&n.flags&&(null===t?e.componentDidMount():(r=n.elementType===n.type?t.memoizedProps:Qa(n.type,t.memoizedProps),e.componentDidUpdate(r,t.memoizedState,e.__reactInternalSnapshotBeforeUpdate))),void(null!==(t=n.updateQueue)&&go(n,t,e));case 3:if(null!==(t=n.updateQueue)){if(e=null,null!==n.child)switch(n.child.tag){case 5:case 1:e=n.child.stateNode}go(n,t,e)}return;case 5:return e=n.stateNode,void(null===t&&4&n.flags&&qr(n.type,n.memoizedProps)&&e.focus());case 6:case 4:case 12:case 19:case 17:case 20:case 21:case 23:case 24:return;case 13:return void(null===n.memoizedState&&(n=n.alternate,null!==n&&(n=n.memoizedState,null!==n&&(n=n.dehydrated,null!==n&&Et(n)))))}throw Error(i(163))}function bl(e,t){for(var n=e;;){if(5===n.tag){var r=n.stateNode;if(t)"function"==typeof(r=r.style).setProperty?r.setProperty("display","none","important"):r.display="none";else{r=n.stateNode;var a=n.memoizedProps.style;a=null!=a&&a.hasOwnProperty("display")?a.display:null,r.style.display=ke("display",a)}}else if(6===n.tag)n.stateNode.nodeValue=t?"":n.memoizedProps;else if((23!==n.tag&&24!==n.tag||null===n.memoizedState||n===e)&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===e)break;for(;null===n.sibling;){if(null===n.return||n.return===e)return;n=n.return}n.sibling.return=n.return,n=n.sibling}}function yl(e,t){if(xa&&"function"==typeof xa.onCommitFiberUnmount)try{xa.onCommitFiberUnmount(Sa,t)}catch(o){}switch(t.tag){case 0:case 11:case 14:case 15:case 22:if(null!==(e=t.updateQueue)&&null!==(e=e.lastEffect)){var n=e=e.next;do{var r=n,a=r.destroy;if(r=r.tag,void 0!==a)if(0!=(4&r))Fs(t,n);else{r=t;try{a()}catch(o){zs(r,o)}}n=n.next}while(n!==e)}break;case 1:if(gl(t),"function"==typeof(e=t.stateNode).componentWillUnmount)try{e.props=t.memoizedProps,e.state=t.memoizedState,e.componentWillUnmount()}catch(o){zs(t,o)}break;case 5:gl(t);break;case 4:Cl(e,t)}}function wl(e){e.alternate=null,e.child=null,e.dependencies=null,e.firstEffect=null,e.lastEffect=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.return=null,e.updateQueue=null}function kl(e){return 5===e.tag||3===e.tag||4===e.tag}function El(e){e:{for(var t=e.return;null!==t;){if(kl(t))break e;t=t.return}throw Error(i(160))}var n=t;switch(t=n.stateNode,n.tag){case 5:var r=!1;break;case 3:case 4:t=t.containerInfo,r=!0;break;default:throw Error(i(161))}16&n.flags&&(be(t,""),n.flags&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||kl(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag&&18!==n.tag;){if(2&n.flags)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.flags)){n=n.stateNode;break e}}r?Sl(e,n,t):xl(e,n,t)}function Sl(e,t,n){var r=e.tag,a=5===r||6===r;if(a)e=a?e.stateNode:e.stateNode.instance,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=zr));else if(4!==r&&null!==(e=e.child))for(Sl(e,t,n),e=e.sibling;null!==e;)Sl(e,t,n),e=e.sibling}function xl(e,t,n){var r=e.tag,a=5===r||6===r;if(a)e=a?e.stateNode:e.stateNode.instance,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(xl(e,t,n),e=e.sibling;null!==e;)xl(e,t,n),e=e.sibling}function Cl(e,t){for(var n,r,a=t,o=!1;;){if(!o){o=a.return;e:for(;;){if(null===o)throw Error(i(160));switch(n=o.stateNode,o.tag){case 5:r=!1;break e;case 3:case 4:n=n.containerInfo,r=!0;break e}o=o.return}o=!0}if(5===a.tag||6===a.tag){e:for(var l=e,s=a,u=s;;)if(yl(l,u),null!==u.child&&4!==u.tag)u.child.return=u,u=u.child;else{if(u===s)break e;for(;null===u.sibling;){if(null===u.return||u.return===s)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}r?(l=n,s=a.stateNode,8===l.nodeType?l.parentNode.removeChild(s):l.removeChild(s)):n.removeChild(a.stateNode)}else if(4===a.tag){if(null!==a.child){n=a.stateNode.containerInfo,r=!0,a.child.return=a,a=a.child;continue}}else if(yl(e,a),null!==a.child){a.child.return=a,a=a.child;continue}if(a===t)break;for(;null===a.sibling;){if(null===a.return||a.return===t)return;4===(a=a.return).tag&&(o=!1)}a.sibling.return=a.return,a=a.sibling}}function _l(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 22:var n=t.updateQueue;if(null!==(n=null!==n?n.lastEffect:null)){var r=n=n.next;do{3==(3&r.tag)&&(e=r.destroy,r.destroy=void 0,void 0!==e&&e()),r=r.next}while(r!==n)}return;case 1:case 12:case 17:return;case 5:if(null!=(n=t.stateNode)){r=t.memoizedProps;var a=null!==e?e.memoizedProps:r;e=t.type;var o=t.updateQueue;if(t.updateQueue=null,null!==o){for(n[Jr]=r,"input"===e&&"radio"===r.type&&null!=r.name&&te(n,r),Ce(e,a),t=Ce(e,r),a=0;a<o.length;a+=2){var l=o[a],s=o[a+1];"style"===l?Ee(n,s):"dangerouslySetInnerHTML"===l?ve(n,s):"children"===l?be(n,s):w(n,l,s,t)}switch(e){case"input":ne(n,r);break;case"textarea":ue(n,r);break;case"select":e=n._wrapperState.wasMultiple,n._wrapperState.wasMultiple=!!r.multiple,null!=(o=r.value)?ie(n,!!r.multiple,o,!1):e!==!!r.multiple&&(null!=r.defaultValue?ie(n,!!r.multiple,r.defaultValue,!0):ie(n,!!r.multiple,r.multiple?[]:"",!1))}}}return;case 6:if(null===t.stateNode)throw Error(i(162));return void(t.stateNode.nodeValue=t.memoizedProps);case 3:return void((n=t.stateNode).hydrate&&(n.hydrate=!1,Et(n.containerInfo)));case 13:return null!==t.memoizedState&&(Hl=qa(),bl(t.child,!0)),void Tl(t);case 19:return void Tl(t);case 23:case 24:return void bl(t,null!==t.memoizedState)}throw Error(i(163))}function Tl(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new ml),t.forEach((function(t){var r=$s.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function Al(e,t){return null!==e&&(null===(e=e.memoizedState)||null!==e.dehydrated)&&(null!==(t=t.memoizedState)&&null===t.dehydrated)}var Ll=Math.ceil,Rl=k.ReactCurrentDispatcher,Pl=k.ReactCurrentOwner,Nl=0,Ol=null,Il=null,Dl=0,Ml=0,Fl=ua(0),jl=0,Bl=null,zl=0,Ul=0,$l=0,ql=0,Gl=null,Hl=0,Zl=1/0;function Vl(){Zl=qa()+500}var Wl,Yl=null,Kl=!1,Ql=null,Xl=null,Jl=!1,es=null,ts=90,ns=[],rs=[],as=null,os=0,is=null,ls=-1,ss=0,us=0,cs=null,ds=!1;function ps(){return 0!=(48&Nl)?qa():-1!==ls?ls:ls=qa()}function fs(e){if(0==(2&(e=e.mode)))return 1;if(0==(4&e))return 99===Ga()?1:2;if(0===ss&&(ss=zl),0!==Ka.transition){0!==us&&(us=null!==Gl?Gl.pendingLanes:0),e=ss;var t=4186112&~us;return 0===(t&=-t)&&(0===(t=(e=4186112&~e)&-e)&&(t=8192)),t}return e=Ga(),0!=(4&Nl)&&98===e?e=zt(12,ss):e=zt(e=function(e){switch(e){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}(e),ss),e}function ms(e,t,n){if(50<os)throw os=0,is=null,Error(i(185));if(null===(e=gs(e,t)))return null;qt(e,t,n),e===Ol&&($l|=t,4===jl&&bs(e,Dl));var r=Ga();1===t?0!=(8&Nl)&&0==(48&Nl)?ys(e):(hs(e,n),0===Nl&&(Vl(),Wa())):(0==(4&Nl)||98!==r&&99!==r||(null===as?as=new Set([e]):as.add(e)),hs(e,n)),Gl=e}function gs(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}function hs(e,t){for(var n=e.callbackNode,r=e.suspendedLanes,a=e.pingedLanes,o=e.expirationTimes,l=e.pendingLanes;0<l;){var s=31-Gt(l),u=1<<s,c=o[s];if(-1===c){if(0==(u&r)||0!=(u&a)){c=t,Ft(u);var d=Mt;o[s]=10<=d?c+250:6<=d?c+5e3:-1}}else c<=t&&(e.expiredLanes|=u);l&=~u}if(r=jt(e,e===Ol?Dl:0),t=Mt,0===r)null!==n&&(n!==Fa&&Ta(n),e.callbackNode=null,e.callbackPriority=0);else{if(null!==n){if(e.callbackPriority===t)return;n!==Fa&&Ta(n)}15===t?(n=ys.bind(null,e),null===Ba?(Ba=[n],za=_a(Na,Ya)):Ba.push(n),n=Fa):14===t?n=Va(99,ys.bind(null,e)):(n=function(e){switch(e){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(i(358,e))}}(t),n=Va(n,vs.bind(null,e))),e.callbackPriority=t,e.callbackNode=n}}function vs(e){if(ls=-1,us=ss=0,0!=(48&Nl))throw Error(i(327));var t=e.callbackNode;if(Ds()&&e.callbackNode!==t)return null;var n=jt(e,e===Ol?Dl:0);if(0===n)return null;var r=n,a=Nl;Nl|=16;var o=_s();for(Ol===e&&Dl===r||(Vl(),xs(e,r));;)try{Ls();break}catch(s){Cs(e,s)}if(no(),Rl.current=o,Nl=a,null!==Il?r=0:(Ol=null,Dl=0,r=jl),0!=(zl&$l))xs(e,0);else if(0!==r){if(2===r&&(Nl|=64,e.hydrate&&(e.hydrate=!1,Vr(e.containerInfo)),0!==(n=Bt(e))&&(r=Ts(e,n))),1===r)throw t=Bl,xs(e,0),bs(e,n),hs(e,qa()),t;switch(e.finishedWork=e.current.alternate,e.finishedLanes=n,r){case 0:case 1:throw Error(i(345));case 2:case 5:Ns(e);break;case 3:if(bs(e,n),(62914560&n)===n&&10<(r=Hl+500-qa())){if(0!==jt(e,0))break;if(((a=e.suspendedLanes)&n)!==n){ps(),e.pingedLanes|=e.suspendedLanes&a;break}e.timeoutHandle=Hr(Ns.bind(null,e),r);break}Ns(e);break;case 4:if(bs(e,n),(4186112&n)===n)break;for(r=e.eventTimes,a=-1;0<n;){var l=31-Gt(n);o=1<<l,(l=r[l])>a&&(a=l),n&=~o}if(n=a,10<(n=(120>(n=qa()-n)?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ll(n/1960))-n)){e.timeoutHandle=Hr(Ns.bind(null,e),n);break}Ns(e);break;default:throw Error(i(329))}}return hs(e,qa()),e.callbackNode===t?vs.bind(null,e):null}function bs(e,t){for(t&=~ql,t&=~$l,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-Gt(t),r=1<<n;e[n]=-1,t&=~r}}function ys(e){if(0!=(48&Nl))throw Error(i(327));if(Ds(),e===Ol&&0!=(e.expiredLanes&Dl)){var t=Dl,n=Ts(e,t);0!=(zl&$l)&&(n=Ts(e,t=jt(e,t)))}else n=Ts(e,t=jt(e,0));if(0!==e.tag&&2===n&&(Nl|=64,e.hydrate&&(e.hydrate=!1,Vr(e.containerInfo)),0!==(t=Bt(e))&&(n=Ts(e,t))),1===n)throw n=Bl,xs(e,0),bs(e,t),hs(e,qa()),n;return e.finishedWork=e.current.alternate,e.finishedLanes=t,Ns(e),hs(e,qa()),null}function ws(e,t){var n=Nl;Nl|=1;try{return e(t)}finally{0===(Nl=n)&&(Vl(),Wa())}}function ks(e,t){var n=Nl;Nl&=-2,Nl|=8;try{return e(t)}finally{0===(Nl=n)&&(Vl(),Wa())}}function Es(e,t){da(Fl,Ml),Ml|=t,zl|=t}function Ss(){Ml=Fl.current,ca(Fl)}function xs(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,Zr(n)),null!==Il)for(n=Il.return;null!==n;){var r=n;switch(r.tag){case 1:null!=(r=r.type.childContextTypes)&&ba();break;case 3:Do(),ca(ma),ca(fa),Ko();break;case 5:Fo(r);break;case 4:Do();break;case 13:case 19:ca(jo);break;case 10:ro(r);break;case 23:case 24:Ss()}n=n.return}Ol=e,Il=Zs(e.current,null),Dl=Ml=zl=t,jl=0,Bl=null,ql=$l=Ul=0}function Cs(e,t){for(;;){var n=Il;try{if(no(),Qo.current=Ni,ri){for(var r=ei.memoizedState;null!==r;){var a=r.queue;null!==a&&(a.pending=null),r=r.next}ri=!1}if(Jo=0,ni=ti=ei=null,ai=!1,Pl.current=null,null===n||null===n.return){jl=1,Bl=t,Il=null;break}e:{var o=e,i=n.return,l=n,s=t;if(t=Dl,l.flags|=2048,l.firstEffect=l.lastEffect=null,null!==s&&"object"==typeof s&&"function"==typeof s.then){var u=s;if(0==(2&l.mode)){var c=l.alternate;c?(l.updateQueue=c.updateQueue,l.memoizedState=c.memoizedState,l.lanes=c.lanes):(l.updateQueue=null,l.memoizedState=null)}var d=0!=(1&jo.current),p=i;do{var f;if(f=13===p.tag){var m=p.memoizedState;if(null!==m)f=null!==m.dehydrated;else{var g=p.memoizedProps;f=void 0!==g.fallback&&(!0!==g.unstable_avoidThisFallback||!d)}}if(f){var h=p.updateQueue;if(null===h){var v=new Set;v.add(u),p.updateQueue=v}else h.add(u);if(0==(2&p.mode)){if(p.flags|=64,l.flags|=16384,l.flags&=-2981,1===l.tag)if(null===l.alternate)l.tag=17;else{var b=co(-1,1);b.tag=2,po(l,b)}l.lanes|=1;break e}s=void 0,l=t;var y=o.pingCache;if(null===y?(y=o.pingCache=new dl,s=new Set,y.set(u,s)):void 0===(s=y.get(u))&&(s=new Set,y.set(u,s)),!s.has(l)){s.add(l);var w=Us.bind(null,o,u,l);u.then(w,w)}p.flags|=4096,p.lanes=t;break e}p=p.return}while(null!==p);s=Error((V(l.type)||"A React component")+" suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.")}5!==jl&&(jl=2),s=ul(s,l),p=i;do{switch(p.tag){case 3:o=s,p.flags|=4096,t&=-t,p.lanes|=t,fo(p,pl(0,o,t));break e;case 1:o=s;var k=p.type,E=p.stateNode;if(0==(64&p.flags)&&("function"==typeof k.getDerivedStateFromError||null!==E&&"function"==typeof E.componentDidCatch&&(null===Xl||!Xl.has(E)))){p.flags|=4096,t&=-t,p.lanes|=t,fo(p,fl(p,o,t));break e}}p=p.return}while(null!==p)}Ps(n)}catch(S){t=S,Il===n&&null!==n&&(Il=n=n.return);continue}break}}function _s(){var e=Rl.current;return Rl.current=Ni,null===e?Ni:e}function Ts(e,t){var n=Nl;Nl|=16;var r=_s();for(Ol===e&&Dl===t||xs(e,t);;)try{As();break}catch(a){Cs(e,a)}if(no(),Nl=n,Rl.current=r,null!==Il)throw Error(i(261));return Ol=null,Dl=0,jl}function As(){for(;null!==Il;)Rs(Il)}function Ls(){for(;null!==Il&&!Aa();)Rs(Il)}function Rs(e){var t=Wl(e.alternate,e,Ml);e.memoizedProps=e.pendingProps,null===t?Ps(e):Il=t,Pl.current=null}function Ps(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(2048&t.flags)){if(null!==(n=ll(n,t,Ml)))return void(Il=n);if(24!==(n=t).tag&&23!==n.tag||null===n.memoizedState||0!=(1073741824&Ml)||0==(4&n.mode)){for(var r=0,a=n.child;null!==a;)r|=a.lanes|a.childLanes,a=a.sibling;n.childLanes=r}null!==e&&0==(2048&e.flags)&&(null===e.firstEffect&&(e.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=t.firstEffect),e.lastEffect=t.lastEffect),1<t.flags&&(null!==e.lastEffect?e.lastEffect.nextEffect=t:e.firstEffect=t,e.lastEffect=t))}else{if(null!==(n=sl(t)))return n.flags&=2047,void(Il=n);null!==e&&(e.firstEffect=e.lastEffect=null,e.flags|=2048)}if(null!==(t=t.sibling))return void(Il=t);Il=t=e}while(null!==t);0===jl&&(jl=5)}function Ns(e){var t=Ga();return Za(99,Os.bind(null,e,t)),null}function Os(e,t){do{Ds()}while(null!==es);if(0!=(48&Nl))throw Error(i(327));var n=e.finishedWork;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(i(177));e.callbackNode=null;var r=n.lanes|n.childLanes,a=r,o=e.pendingLanes&~a;e.pendingLanes=a,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=a,e.mutableReadLanes&=a,e.entangledLanes&=a,a=e.entanglements;for(var l=e.eventTimes,s=e.expirationTimes;0<o;){var u=31-Gt(o),c=1<<u;a[u]=0,l[u]=-1,s[u]=-1,o&=~c}if(null!==as&&0==(24&r)&&as.has(e)&&as.delete(e),e===Ol&&(Il=Ol=null,Dl=0),1<n.flags?null!==n.lastEffect?(n.lastEffect.nextEffect=n,r=n.firstEffect):r=n:r=n.firstEffect,null!==r){if(a=Nl,Nl|=32,Pl.current=null,Ur=Yt,vr(l=hr())){if("selectionStart"in l)s={start:l.selectionStart,end:l.selectionEnd};else e:if(s=(s=l.ownerDocument)&&s.defaultView||window,(c=s.getSelection&&s.getSelection())&&0!==c.rangeCount){s=c.anchorNode,o=c.anchorOffset,u=c.focusNode,c=c.focusOffset;try{s.nodeType,u.nodeType}catch(_){s=null;break e}var d=0,p=-1,f=-1,m=0,g=0,h=l,v=null;t:for(;;){for(var b;h!==s||0!==o&&3!==h.nodeType||(p=d+o),h!==u||0!==c&&3!==h.nodeType||(f=d+c),3===h.nodeType&&(d+=h.nodeValue.length),null!==(b=h.firstChild);)v=h,h=b;for(;;){if(h===l)break t;if(v===s&&++m===o&&(p=d),v===u&&++g===c&&(f=d),null!==(b=h.nextSibling))break;v=(h=v).parentNode}h=b}s=-1===p||-1===f?null:{start:p,end:f}}else s=null;s=s||{start:0,end:0}}else s=null;$r={focusedElem:l,selectionRange:s},Yt=!1,cs=null,ds=!1,Yl=r;do{try{Is()}catch(_){if(null===Yl)throw Error(i(330));zs(Yl,_),Yl=Yl.nextEffect}}while(null!==Yl);cs=null,Yl=r;do{try{for(l=e;null!==Yl;){var y=Yl.flags;if(16&y&&be(Yl.stateNode,""),128&y){var w=Yl.alternate;if(null!==w){var k=w.ref;null!==k&&("function"==typeof k?k(null):k.current=null)}}switch(1038&y){case 2:El(Yl),Yl.flags&=-3;break;case 6:El(Yl),Yl.flags&=-3,_l(Yl.alternate,Yl);break;case 1024:Yl.flags&=-1025;break;case 1028:Yl.flags&=-1025,_l(Yl.alternate,Yl);break;case 4:_l(Yl.alternate,Yl);break;case 8:Cl(l,s=Yl);var E=s.alternate;wl(s),null!==E&&wl(E)}Yl=Yl.nextEffect}}catch(_){if(null===Yl)throw Error(i(330));zs(Yl,_),Yl=Yl.nextEffect}}while(null!==Yl);if(k=$r,w=hr(),y=k.focusedElem,l=k.selectionRange,w!==y&&y&&y.ownerDocument&&gr(y.ownerDocument.documentElement,y)){null!==l&&vr(y)&&(w=l.start,void 0===(k=l.end)&&(k=w),"selectionStart"in y?(y.selectionStart=w,y.selectionEnd=Math.min(k,y.value.length)):(k=(w=y.ownerDocument||document)&&w.defaultView||window).getSelection&&(k=k.getSelection(),s=y.textContent.length,E=Math.min(l.start,s),l=void 0===l.end?E:Math.min(l.end,s),!k.extend&&E>l&&(s=l,l=E,E=s),s=mr(y,E),o=mr(y,l),s&&o&&(1!==k.rangeCount||k.anchorNode!==s.node||k.anchorOffset!==s.offset||k.focusNode!==o.node||k.focusOffset!==o.offset)&&((w=w.createRange()).setStart(s.node,s.offset),k.removeAllRanges(),E>l?(k.addRange(w),k.extend(o.node,o.offset)):(w.setEnd(o.node,o.offset),k.addRange(w))))),w=[];for(k=y;k=k.parentNode;)1===k.nodeType&&w.push({element:k,left:k.scrollLeft,top:k.scrollTop});for("function"==typeof y.focus&&y.focus(),y=0;y<w.length;y++)(k=w[y]).element.scrollLeft=k.left,k.element.scrollTop=k.top}Yt=!!Ur,$r=Ur=null,e.current=n,Yl=r;do{try{for(y=e;null!==Yl;){var S=Yl.flags;if(36&S&&vl(y,Yl.alternate,Yl),128&S){w=void 0;var x=Yl.ref;if(null!==x){var C=Yl.stateNode;Yl.tag,w=C,"function"==typeof x?x(w):x.current=w}}Yl=Yl.nextEffect}}catch(_){if(null===Yl)throw Error(i(330));zs(Yl,_),Yl=Yl.nextEffect}}while(null!==Yl);Yl=null,ja(),Nl=a}else e.current=n;if(Jl)Jl=!1,es=e,ts=t;else for(Yl=r;null!==Yl;)t=Yl.nextEffect,Yl.nextEffect=null,8&Yl.flags&&((S=Yl).sibling=null,S.stateNode=null),Yl=t;if(0===(r=e.pendingLanes)&&(Xl=null),1===r?e===is?os++:(os=0,is=e):os=0,n=n.stateNode,xa&&"function"==typeof xa.onCommitFiberRoot)try{xa.onCommitFiberRoot(Sa,n,void 0,64==(64&n.current.flags))}catch(_){}if(hs(e,qa()),Kl)throw Kl=!1,e=Ql,Ql=null,e;return 0!=(8&Nl)||Wa(),null}function Is(){for(;null!==Yl;){var e=Yl.alternate;ds||null===cs||(0!=(8&Yl.flags)?et(Yl,cs)&&(ds=!0):13===Yl.tag&&Al(e,Yl)&&et(Yl,cs)&&(ds=!0));var t=Yl.flags;0!=(256&t)&&hl(e,Yl),0==(512&t)||Jl||(Jl=!0,Va(97,(function(){return Ds(),null}))),Yl=Yl.nextEffect}}function Ds(){if(90!==ts){var e=97<ts?97:ts;return ts=90,Za(e,js)}return!1}function Ms(e,t){ns.push(t,e),Jl||(Jl=!0,Va(97,(function(){return Ds(),null})))}function Fs(e,t){rs.push(t,e),Jl||(Jl=!0,Va(97,(function(){return Ds(),null})))}function js(){if(null===es)return!1;var e=es;if(es=null,0!=(48&Nl))throw Error(i(331));var t=Nl;Nl|=32;var n=rs;rs=[];for(var r=0;r<n.length;r+=2){var a=n[r],o=n[r+1],l=a.destroy;if(a.destroy=void 0,"function"==typeof l)try{l()}catch(u){if(null===o)throw Error(i(330));zs(o,u)}}for(n=ns,ns=[],r=0;r<n.length;r+=2){a=n[r],o=n[r+1];try{var s=a.create;a.destroy=s()}catch(u){if(null===o)throw Error(i(330));zs(o,u)}}for(s=e.current.firstEffect;null!==s;)e=s.nextEffect,s.nextEffect=null,8&s.flags&&(s.sibling=null,s.stateNode=null),s=e;return Nl=t,Wa(),!0}function Bs(e,t,n){po(e,t=pl(0,t=ul(n,t),1)),t=ps(),null!==(e=gs(e,1))&&(qt(e,1,t),hs(e,t))}function zs(e,t){if(3===e.tag)Bs(e,e,t);else for(var n=e.return;null!==n;){if(3===n.tag){Bs(n,e,t);break}if(1===n.tag){var r=n.stateNode;if("function"==typeof n.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===Xl||!Xl.has(r))){var a=fl(n,e=ul(t,e),1);if(po(n,a),a=ps(),null!==(n=gs(n,1)))qt(n,1,a),hs(n,a);else if("function"==typeof r.componentDidCatch&&(null===Xl||!Xl.has(r)))try{r.componentDidCatch(t,e)}catch(o){}break}}n=n.return}}function Us(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=ps(),e.pingedLanes|=e.suspendedLanes&n,Ol===e&&(Dl&n)===n&&(4===jl||3===jl&&(62914560&Dl)===Dl&&500>qa()-Hl?xs(e,0):ql|=n),hs(e,t)}function $s(e,t){var n=e.stateNode;null!==n&&n.delete(t),0===(t=0)&&(0==(2&(t=e.mode))?t=1:0==(4&t)?t=99===Ga()?1:2:(0===ss&&(ss=zl),0===(t=Ut(62914560&~ss))&&(t=4194304))),n=ps(),null!==(e=gs(e,t))&&(qt(e,t,n),hs(e,n))}function qs(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function Gs(e,t,n,r){return new qs(e,t,n,r)}function Hs(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Zs(e,t){var n=e.alternate;return null===n?((n=Gs(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Vs(e,t,n,r,a,o){var l=2;if(r=e,"function"==typeof e)Hs(e)&&(l=1);else if("string"==typeof e)l=5;else e:switch(e){case x:return Ws(n.children,a,o,t);case M:l=8,a|=16;break;case C:l=8,a|=1;break;case _:return(e=Gs(12,n,t,8|a)).elementType=_,e.type=_,e.lanes=o,e;case R:return(e=Gs(13,n,t,a)).type=R,e.elementType=R,e.lanes=o,e;case P:return(e=Gs(19,n,t,a)).elementType=P,e.lanes=o,e;case F:return Ys(n,a,o,t);case j:return(e=Gs(24,n,t,a)).elementType=j,e.lanes=o,e;default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case T:l=10;break e;case A:l=9;break e;case L:l=11;break e;case N:l=14;break e;case O:l=16,r=null;break e;case I:l=22;break e}throw Error(i(130,null==e?e:typeof e,""))}return(t=Gs(l,n,t,a)).elementType=e,t.type=r,t.lanes=o,t}function Ws(e,t,n,r){return(e=Gs(7,e,r,t)).lanes=n,e}function Ys(e,t,n,r){return(e=Gs(23,e,r,t)).elementType=F,e.lanes=n,e}function Ks(e,t,n){return(e=Gs(6,e,null,t)).lanes=n,e}function Qs(e,t,n){return(t=Gs(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xs(e,t,n){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.pendingContext=this.context=null,this.hydrate=n,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=$t(0),this.expirationTimes=$t(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=$t(0),this.mutableSourceEagerHydrationData=null}function Js(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:S,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}function eu(e,t,n,r){var a=t.current,o=ps(),l=fs(a);e:if(n){t:{if(Ke(n=n._reactInternals)!==n||1!==n.tag)throw Error(i(170));var s=n;do{switch(s.tag){case 3:s=s.stateNode.context;break t;case 1:if(va(s.type)){s=s.stateNode.__reactInternalMemoizedMergedChildContext;break t}}s=s.return}while(null!==s);throw Error(i(171))}if(1===n.tag){var u=n.type;if(va(u)){n=wa(n,u,s);break e}}n=s}else n=pa;return null===t.context?t.context=n:t.pendingContext=n,(t=co(o,l)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),po(a,t),ms(a,l,o),l}function tu(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function nu(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function ru(e,t){nu(e,t),(e=e.alternate)&&nu(e,t)}function au(e,t,n){var r=null!=n&&null!=n.hydrationOptions&&n.hydrationOptions.mutableSources||null;if(n=new Xs(e,t,null!=n&&!0===n.hydrate),t=Gs(3,null,null,2===t?7:1===t?3:0),n.current=t,t.stateNode=n,so(t),e[ea]=n.current,Nr(8===e.nodeType?e.parentNode:e),r)for(e=0;e<r.length;e++){var a=(t=r[e])._getVersion;a=a(t._source),null==n.mutableSourceEagerHydrationData?n.mutableSourceEagerHydrationData=[t,a]:n.mutableSourceEagerHydrationData.push(t,a)}this._internalRoot=n}function ou(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function iu(e,t,n,r,a){var o=n._reactRootContainer;if(o){var i=o._internalRoot;if("function"==typeof a){var l=a;a=function(){var e=tu(i);l.call(e)}}eu(t,i,e,a)}else{if(o=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute("data-reactroot"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new au(e,0,t?{hydrate:!0}:void 0)}(n,r),i=o._internalRoot,"function"==typeof a){var s=a;a=function(){var e=tu(i);s.call(e)}}ks((function(){eu(t,i,e,a)}))}return tu(i)}function lu(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!ou(t))throw Error(i(200));return Js(e,t,null,n)}Wl=function(e,t,n){var r=t.lanes;if(null!==e)if(e.memoizedProps!==t.pendingProps||ma.current)Fi=!0;else{if(0==(n&r)){switch(Fi=!1,t.tag){case 3:Vi(t),Wo();break;case 5:Mo(t);break;case 1:va(t.type)&&ka(t);break;case 4:Io(t,t.stateNode.containerInfo);break;case 10:r=t.memoizedProps.value;var a=t.type._context;da(Xa,a._currentValue),a._currentValue=r;break;case 13:if(null!==t.memoizedState)return 0!=(n&t.child.childLanes)?Xi(e,t,n):(da(jo,1&jo.current),null!==(t=ol(e,t,n))?t.sibling:null);da(jo,1&jo.current);break;case 19:if(r=0!=(n&t.childLanes),0!=(64&e.flags)){if(r)return al(e,t,n);t.flags|=64}if(null!==(a=t.memoizedState)&&(a.rendering=null,a.tail=null,a.lastEffect=null),da(jo,jo.current),r)break;return null;case 23:case 24:return t.lanes=0,$i(e,t,n)}return ol(e,t,n)}Fi=0!=(16384&e.flags)}else Fi=!1;switch(t.lanes=0,t.tag){case 2:if(r=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,a=ha(t,fa.current),oo(t,n),a=li(null,t,r,e,a,n),t.flags|=1,"object"==typeof a&&null!==a&&"function"==typeof a.render&&void 0===a.$$typeof){if(t.tag=1,t.memoizedState=null,t.updateQueue=null,va(r)){var o=!0;ka(t)}else o=!1;t.memoizedState=null!==a.state&&void 0!==a.state?a.state:null,so(t);var l=r.getDerivedStateFromProps;"function"==typeof l&&vo(t,r,l,e),a.updater=bo,t.stateNode=a,a._reactInternals=t,Eo(t,r,e,n),t=Zi(null,t,r,!0,o,n)}else t.tag=0,ji(null,t,a,n),t=t.child;return t;case 16:a=t.elementType;e:{switch(null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,a=(o=a._init)(a._payload),t.type=a,o=t.tag=function(e){if("function"==typeof e)return Hs(e)?1:0;if(null!=e){if((e=e.$$typeof)===L)return 11;if(e===N)return 14}return 2}(a),e=Qa(a,e),o){case 0:t=Gi(null,t,a,e,n);break e;case 1:t=Hi(null,t,a,e,n);break e;case 11:t=Bi(null,t,a,e,n);break e;case 14:t=zi(null,t,a,Qa(a.type,e),r,n);break e}throw Error(i(306,a,""))}return t;case 0:return r=t.type,a=t.pendingProps,Gi(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 1:return r=t.type,a=t.pendingProps,Hi(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 3:if(Vi(t),r=t.updateQueue,null===e||null===r)throw Error(i(282));if(r=t.pendingProps,a=null!==(a=t.memoizedState)?a.element:null,uo(e,t),mo(t,r,null,n),(r=t.memoizedState.element)===a)Wo(),t=ol(e,t,n);else{if((o=(a=t.stateNode).hydrate)&&(Uo=Wr(t.stateNode.containerInfo.firstChild),zo=t,o=$o=!0),o){if(null!=(e=a.mutableSourceEagerHydrationData))for(a=0;a<e.length;a+=2)(o=e[a])._workInProgressVersionPrimary=e[a+1],Yo.push(o);for(n=Ao(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|1024,n=n.sibling}else ji(e,t,r,n),Wo();t=t.child}return t;case 5:return Mo(t),null===e&&Ho(t),r=t.type,a=t.pendingProps,o=null!==e?e.memoizedProps:null,l=a.children,Gr(r,a)?l=null:null!==o&&Gr(r,o)&&(t.flags|=16),qi(e,t),ji(e,t,l,n),t.child;case 6:return null===e&&Ho(t),null;case 13:return Xi(e,t,n);case 4:return Io(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=To(t,null,r,n):ji(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,Bi(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 7:return ji(e,t,t.pendingProps,n),t.child;case 8:case 12:return ji(e,t,t.pendingProps.children,n),t.child;case 10:e:{r=t.type._context,a=t.pendingProps,l=t.memoizedProps,o=a.value;var s=t.type._context;if(da(Xa,s._currentValue),s._currentValue=o,null!==l)if(s=l.value,0===(o=cr(s,o)?0:0|("function"==typeof r._calculateChangedBits?r._calculateChangedBits(s,o):1073741823))){if(l.children===a.children&&!ma.current){t=ol(e,t,n);break e}}else for(null!==(s=t.child)&&(s.return=t);null!==s;){var u=s.dependencies;if(null!==u){l=s.child;for(var c=u.firstContext;null!==c;){if(c.context===r&&0!=(c.observedBits&o)){1===s.tag&&((c=co(-1,n&-n)).tag=2,po(s,c)),s.lanes|=n,null!==(c=s.alternate)&&(c.lanes|=n),ao(s.return,n),u.lanes|=n;break}c=c.next}}else l=10===s.tag&&s.type===t.type?null:s.child;if(null!==l)l.return=s;else for(l=s;null!==l;){if(l===t){l=null;break}if(null!==(s=l.sibling)){s.return=l.return,l=s;break}l=l.return}s=l}ji(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=(o=t.pendingProps).children,oo(t,n),r=r(a=io(a,o.unstable_observedBits)),t.flags|=1,ji(e,t,r,n),t.child;case 14:return o=Qa(a=t.type,t.pendingProps),zi(e,t,a,o=Qa(a.type,o),r,n);case 15:return Ui(e,t,t.type,t.pendingProps,r,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Qa(r,a),null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),t.tag=1,va(r)?(e=!0,ka(t)):e=!1,oo(t,n),wo(t,r,a),Eo(t,r,a,n),Zi(null,t,r,!0,e,n);case 19:return al(e,t,n);case 23:case 24:return $i(e,t,n)}throw Error(i(156,t.tag))},au.prototype.render=function(e){eu(e,this._internalRoot,null,null)},au.prototype.unmount=function(){var e=this._internalRoot,t=e.containerInfo;eu(null,e,null,(function(){t[ea]=null}))},tt=function(e){13===e.tag&&(ms(e,4,ps()),ru(e,4))},nt=function(e){13===e.tag&&(ms(e,67108864,ps()),ru(e,67108864))},rt=function(e){if(13===e.tag){var t=ps(),n=fs(e);ms(e,n,t),ru(e,n)}},at=function(e,t){return t()},Te=function(e,t,n){switch(t){case"input":if(ne(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var a=oa(r);if(!a)throw Error(i(90));Q(r),ne(r,a)}}}break;case"textarea":ue(e,n);break;case"select":null!=(t=n.value)&&ie(e,!!n.multiple,t,!1)}},Oe=ws,Ie=function(e,t,n,r,a){var o=Nl;Nl|=4;try{return Za(98,e.bind(null,t,n,r,a))}finally{0===(Nl=o)&&(Vl(),Wa())}},De=function(){0==(49&Nl)&&(function(){if(null!==as){var e=as;as=null,e.forEach((function(e){e.expiredLanes|=24&e.pendingLanes,hs(e,qa())}))}Wa()}(),Ds())},Me=function(e,t){var n=Nl;Nl|=2;try{return e(t)}finally{0===(Nl=n)&&(Vl(),Wa())}};var su={Events:[ra,aa,oa,Pe,Ne,Ds,{current:!1}]},uu={findFiberByHostInstance:na,bundleType:0,version:"17.0.2",rendererPackageName:"react-dom"},cu={bundleType:uu.bundleType,version:uu.version,rendererPackageName:uu.rendererPackageName,rendererConfig:uu.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:k.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Je(e))?null:e.stateNode},findFiberByHostInstance:uu.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var du=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!du.isDisabled&&du.supportsFiber)try{Sa=du.inject(cu),xa=du}catch(he){}}t.hydrate=function(e,t,n){if(!ou(t))throw Error(i(200));return iu(null,e,t,!0,n)}},3935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(4448)},9590:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,a="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function o(e,i){if(e===i)return!0;if(e&&i&&"object"==typeof e&&"object"==typeof i){if(e.constructor!==i.constructor)return!1;var l,s,u,c;if(Array.isArray(e)){if((l=e.length)!=i.length)return!1;for(s=l;0!=s--;)if(!o(e[s],i[s]))return!1;return!0}if(n&&e instanceof Map&&i instanceof Map){if(e.size!==i.size)return!1;for(c=e.entries();!(s=c.next()).done;)if(!i.has(s.value[0]))return!1;for(c=e.entries();!(s=c.next()).done;)if(!o(s.value[1],i.get(s.value[0])))return!1;return!0}if(r&&e instanceof Set&&i instanceof Set){if(e.size!==i.size)return!1;for(c=e.entries();!(s=c.next()).done;)if(!i.has(s.value[0]))return!1;return!0}if(a&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(i)){if((l=e.length)!=i.length)return!1;for(s=l;0!=s--;)if(e[s]!==i[s])return!1;return!0}if(e.constructor===RegExp)return e.source===i.source&&e.flags===i.flags;if(e.valueOf!==Object.prototype.valueOf)return e.valueOf()===i.valueOf();if(e.toString!==Object.prototype.toString)return e.toString()===i.toString();if((l=(u=Object.keys(e)).length)!==Object.keys(i).length)return!1;for(s=l;0!=s--;)if(!Object.prototype.hasOwnProperty.call(i,u[s]))return!1;if(t&&e instanceof Element)return!1;for(s=l;0!=s--;)if(("_owner"!==u[s]&&"__v"!==u[s]&&"__o"!==u[s]||!e.$$typeof)&&!o(e[u[s]],i[u[s]]))return!1;return!0}return e!=e&&i!=i}e.exports=function(e,t){try{return o(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},405:(e,t,n)=>{"use strict";n.d(t,{B6:()=>H,ql:()=>J});var r=n(7294),a=n(5697),o=n.n(a),i=n(9590),l=n.n(i),s=n(1143),u=n.n(s),c=n(6774),d=n.n(c);function p(){return p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},p.apply(this,arguments)}function f(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function g(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(a[n]=e[n]);return a}var h={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},v={rel:["amphtml","canonical","alternate"]},b={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},w=Object.keys(h).map((function(e){return h[e]})),k={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},E=Object.keys(k).reduce((function(e,t){return e[k[t]]=t,e}),{}),S=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},x=function(e){var t=S(e,h.TITLE),n=S(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var r=S(e,"defaultTitle");return t||r||void 0},C=function(e){return S(e,"onChangeClientState")||function(){}},_=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return p({},e,t)}),{})},T=function(e,t){return t.filter((function(e){return void 0!==e[h.BASE]})).map((function(e){return e[h.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),a=0;a<r.length;a+=1){var o=r[a].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t}),[])},A=function(e,t,n){var r={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var a={};n.filter((function(e){for(var n,o=Object.keys(e),i=0;i<o.length;i+=1){var l=o[i],s=l.toLowerCase();-1===t.indexOf(s)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===s&&"stylesheet"===e[s].toLowerCase()||(n=s),-1===t.indexOf(l)||"innerHTML"!==l&&"cssText"!==l&&"itemprop"!==l||(n=l)}if(!n||!e[n])return!1;var u=e[n].toLowerCase();return r[n]||(r[n]={}),a[n]||(a[n]={}),!r[n][u]&&(a[n][u]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var o=Object.keys(a),i=0;i<o.length;i+=1){var l=o[i],s=p({},r[l],a[l]);r[l]=s}return e}),[]).reverse()},L=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},R=function(e){return Array.isArray(e)?e.join(""):e},P=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},N=function(e,t){var n;return p({},e,((n={})[t]=void 0,n))},O=[h.NOSCRIPT,h.SCRIPT,h.STYLE],I=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},D=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},M=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[k[n]||n]=e[n],t}),t)},F=function(e,t){return t.map((function(t,n){var a,o=((a={key:n})["data-rh"]=!0,a);return Object.keys(t).forEach((function(e){var n=k[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]})),r.createElement(e,o)}))},j=function(e,t,n){switch(e){case h.TITLE:return{toComponent:function(){return n=t.titleAttributes,(a={key:e=t.title})["data-rh"]=!0,o=M(n,a),[r.createElement(h.TITLE,o,e)];var e,n,a,o},toString:function(){return function(e,t,n,r){var a=D(n),o=R(t);return a?"<"+e+' data-rh="true" '+a+">"+I(o,r)+"</"+e+">":"<"+e+' data-rh="true">'+I(o,r)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return M(t)},toString:function(){return D(t)}};default:return{toComponent:function(){return F(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var a=Object.keys(r).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var a=void 0===r[t]?t:t+'="'+I(r[t],n)+'"';return e?e+" "+a:a}),""),o=r.innerHTML||r.cssText||"",i=-1===O.indexOf(e);return t+"<"+e+' data-rh="true" '+a+(i?"/>":">"+o+"</"+e+">")}),"")}(e,t,n)}}}},B=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,a=e.htmlAttributes,o=e.noscriptTags,i=e.styleTags,l=e.title,s=void 0===l?"":l,u=e.titleAttributes,c=e.linkTags,d=e.metaTags,p=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,r=e.encode,a=P(e.metaTags,y),o=P(t,v),i=P(n,b);return{priorityMethods:{toComponent:function(){return[].concat(F(h.META,a.priority),F(h.LINK,o.priority),F(h.SCRIPT,i.priority))},toString:function(){return j(h.META,a.priority,r)+" "+j(h.LINK,o.priority,r)+" "+j(h.SCRIPT,i.priority,r)}},metaTags:a.default,linkTags:o.default,scriptTags:i.default}}(e);f=m.priorityMethods,c=m.linkTags,d=m.metaTags,p=m.scriptTags}return{priority:f,base:j(h.BASE,t,r),bodyAttributes:j("bodyAttributes",n,r),htmlAttributes:j("htmlAttributes",a,r),link:j(h.LINK,c,r),meta:j(h.META,d,r),noscript:j(h.NOSCRIPT,o,r),script:j(h.SCRIPT,p,r),style:j(h.STYLE,i,r),title:j(h.TITLE,{title:s,titleAttributes:u},r)}},z=[],U=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?z:n.instances},add:function(e){(n.canUseDOM?z:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?z:n.instances).indexOf(e);(n.canUseDOM?z:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=B({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},$=r.createContext({}),q=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),G="undefined"!=typeof document,H=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new U(r.props.context,t.canUseDOM),r}return f(t,e),t.prototype.render=function(){return r.createElement($.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);H.canUseDOM=G,H.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},H.defaultProps={context:{}},H.displayName="HelmetProvider";var Z=function(e,t){var n,r=document.head||document.querySelector(h.HEAD),a=r.querySelectorAll(e+"[data-rh]"),o=[].slice.call(a),i=[];return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&("innerHTML"===a?r.innerHTML=t.innerHTML:"cssText"===a?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(a,void 0===t[a]?"":t[a]));r.setAttribute("data-rh","true"),o.some((function(e,t){return n=t,r.isEqualNode(e)}))?o.splice(n,1):i.push(r)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:o,newTags:i}},V=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),a=r?r.split(","):[],o=[].concat(a),i=Object.keys(t),l=0;l<i.length;l+=1){var s=i[l],u=t[s]||"";n.getAttribute(s)!==u&&n.setAttribute(s,u),-1===a.indexOf(s)&&a.push(s);var c=o.indexOf(s);-1!==c&&o.splice(c,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);a.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},W=function(e,t){var n=e.baseTag,r=e.htmlAttributes,a=e.linkTags,o=e.metaTags,i=e.noscriptTags,l=e.onChangeClientState,s=e.scriptTags,u=e.styleTags,c=e.title,d=e.titleAttributes;V(h.BODY,e.bodyAttributes),V(h.HTML,r),function(e,t){void 0!==e&&document.title!==e&&(document.title=R(e)),V(h.TITLE,t)}(c,d);var p={baseTag:Z(h.BASE,n),linkTags:Z(h.LINK,a),metaTags:Z(h.META,o),noscriptTags:Z(h.NOSCRIPT,i),scriptTags:Z(h.SCRIPT,s),styleTags:Z(h.STYLE,u)},f={},m={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,r=t.oldTags;n.length&&(f[e]=n),r.length&&(m[e]=p[e].oldTags)})),t&&t(),l(e,f,m)},Y=null,K=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,a=null,o=(e=n.helmetInstances.get().map((function(e){var t=p({},e.props);return delete t.context,t})),{baseTag:T(["href"],e),bodyAttributes:_("bodyAttributes",e),defer:S(e,"defer"),encode:S(e,"encodeSpecialCharacters"),htmlAttributes:_("htmlAttributes",e),linkTags:A(h.LINK,["rel","href"],e),metaTags:A(h.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:A(h.NOSCRIPT,["innerHTML"],e),onChangeClientState:C(e),scriptTags:A(h.SCRIPT,["src","innerHTML"],e),styleTags:A(h.STYLE,["cssText"],e),title:x(e),titleAttributes:_("titleAttributes",e),prioritizeSeoTags:L(e,"prioritizeSeoTags")});H.canUseDOM?(t=o,Y&&cancelAnimationFrame(Y),t.defer?Y=requestAnimationFrame((function(){W(t,(function(){Y=null}))})):(W(t),Y=null)):B&&(a=B(o)),r(a)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);K.propTypes={context:q.isRequired},K.displayName="HelmetDispatcher";var Q=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!l()(N(this.props,"helmetData"),N(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case h.SCRIPT:case h.NOSCRIPT:return{innerHTML:t};case h.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return p({},r,((t={})[n.type]=[].concat(r[n.type]||[],[p({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,a=e.newProps,o=e.newChildProps,i=e.nestedChildren;switch(r.type){case h.TITLE:return p({},a,((t={})[r.type]=i,t.titleAttributes=p({},o),t));case h.BODY:return p({},a,{bodyAttributes:p({},o)});case h.HTML:return p({},a,{htmlAttributes:p({},o)});default:return p({},a,((n={})[r.type]=p({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=p({},t);return Object.keys(e).forEach((function(t){var r;n=p({},n,((r={})[t]=e[t],r))})),n},n.warnOnInvalidChildren=function(e,t){return u()(w.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+w.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),u()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,a={};return r.Children.forEach(e,(function(e){if(e&&e.props){var r=e.props,o=r.children,i=g(r,Q),l=Object.keys(i).reduce((function(e,t){return e[E[t]||t]=i[t],e}),{}),s=e.type;switch("symbol"==typeof s?s=s.toString():n.warnOnInvalidChildren(e,o),s){case h.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case h.LINK:case h.META:case h.NOSCRIPT:case h.SCRIPT:case h.STYLE:a=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:a,newChildProps:l,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:l,nestedChildren:o})}}})),this.mapArrayTypeChildrenToProps(a,t)},n.render=function(){var e=this.props,t=e.children,n=g(e,X),a=p({},n),o=n.helmetData;return t&&(a=this.mapChildrenToProps(t,a)),!o||o instanceof U||(o=new U(o.context,o.instances)),o?r.createElement(K,p({},a,{context:o.value,helmetData:void 0})):r.createElement($.Consumer,null,(function(e){return r.createElement(K,p({},a,{context:e}))}))},t}(r.Component);J.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},9921:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,a=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,l=n?Symbol.for("react.profiler"):60114,s=n?Symbol.for("react.provider"):60109,u=n?Symbol.for("react.context"):60110,c=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,p=n?Symbol.for("react.forward_ref"):60112,f=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,g=n?Symbol.for("react.memo"):60115,h=n?Symbol.for("react.lazy"):60116,v=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function k(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case c:case d:case o:case l:case i:case f:return e;default:switch(e=e&&e.$$typeof){case u:case p:case h:case g:case s:return e;default:return t}}case a:return t}}}function E(e){return k(e)===d}t.AsyncMode=c,t.ConcurrentMode=d,t.ContextConsumer=u,t.ContextProvider=s,t.Element=r,t.ForwardRef=p,t.Fragment=o,t.Lazy=h,t.Memo=g,t.Portal=a,t.Profiler=l,t.StrictMode=i,t.Suspense=f,t.isAsyncMode=function(e){return E(e)||k(e)===c},t.isConcurrentMode=E,t.isContextConsumer=function(e){return k(e)===u},t.isContextProvider=function(e){return k(e)===s},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return k(e)===p},t.isFragment=function(e){return k(e)===o},t.isLazy=function(e){return k(e)===h},t.isMemo=function(e){return k(e)===g},t.isPortal=function(e){return k(e)===a},t.isProfiler=function(e){return k(e)===l},t.isStrictMode=function(e){return k(e)===i},t.isSuspense=function(e){return k(e)===f},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===l||e===i||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===g||e.$$typeof===s||e.$$typeof===u||e.$$typeof===p||e.$$typeof===b||e.$$typeof===y||e.$$typeof===w||e.$$typeof===v)},t.typeOf=k},9864:(e,t,n)=>{"use strict";e.exports=n(9921)},8356:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i.apply(this,arguments)}var l=n(7294),s=n(5697),u=[],c=[];function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function p(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var a=d(e[r]);a.loading?t.loading=!0:(t.loaded[r]=a.loaded,t.error=a.error),n.push(a.promise),a.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function f(e,t){return l.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,p;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=i({loader:null,loading:null,delay:200,timeout:null,render:f,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return u.push(h),"function"==typeof m.webpack&&c.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h()})),p=d=function(t){function n(n){var r;return o(a(a(r=t.call(this,n)||this)),"retry",(function(){r.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),r._loadModule()})),h(),r.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},r}r(n,t),n.preload=function(){return h()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),g.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts()};g.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?l.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(l.Component),o(d,"contextTypes",{loadable:s.shape({report:s.func.isRequired})}),p}function g(e){return m(d,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(p,e)};var h=function(e){function t(){return e.apply(this,arguments)||this}r(t,e);var n=t.prototype;return n.getChildContext=function(){return{loadable:{report:this.props.report}}},n.render=function(){return l.Children.only(this.props.children)},t}(l.Component);function v(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return v(e)}))}o(h,"propTypes",{report:s.func.isRequired}),o(h,"childContextTypes",{loadable:s.shape({report:s.func.isRequired}).isRequired}),g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){v(u).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){v(c).then(e,e)}))},e.exports=g},8790:(e,t,n)=>{"use strict";n.d(t,{H:()=>l,f:()=>i});var r=n(6550),a=n(7462),o=n(7294);function i(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var a=e.path?(0,r.LX)(t,e):n.length?n[n.length-1].match:r.F0.computeRootMatch(t);return a&&(n.push({route:e,match:a}),e.routes&&i(e.routes,t,n)),a})),n}function l(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?o.createElement(r.rs,n,e.map((function(e,n){return o.createElement(r.AW,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,a.Z)({},n,{},t,{route:e})):o.createElement(e.component,(0,a.Z)({},n,t,{route:e}))}})}))):null}},3727:(e,t,n)=>{"use strict";n.d(t,{OL:()=>y,VK:()=>c,rU:()=>h});var r=n(6550),a=n(5068),o=n(7294),i=n(9318),l=n(7462),s=n(3366),u=n(8776),c=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.lX)(t.props),t}return(0,a.Z)(t,e),t.prototype.render=function(){return o.createElement(r.F0,{history:this.history,children:this.props.children})},t}(o.Component);o.Component;var d=function(e,t){return"function"==typeof e?e(t):e},p=function(e,t){return"string"==typeof e?(0,i.ob)(e,null,null,t):e},f=function(e){return e},m=o.forwardRef;void 0===m&&(m=f);var g=m((function(e,t){var n=e.innerRef,r=e.navigate,a=e.onClick,i=(0,s.Z)(e,["innerRef","navigate","onClick"]),u=i.target,c=(0,l.Z)({},i,{onClick:function(e){try{a&&a(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||u&&"_self"!==u||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),r())}});return c.ref=f!==m&&t||n,o.createElement("a",c)}));var h=m((function(e,t){var n=e.component,a=void 0===n?g:n,c=e.replace,h=e.to,v=e.innerRef,b=(0,s.Z)(e,["component","replace","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,u.Z)(!1);var n=e.history,r=p(d(h,e.location),e.location),s=r?n.createHref(r):"",g=(0,l.Z)({},b,{href:s,navigate:function(){var t=d(h,e.location),r=(0,i.Ep)(e.location)===(0,i.Ep)(p(t));(c||r?n.replace:n.push)(t)}});return f!==m?g.ref=t||v:g.innerRef=v,o.createElement(a,g)}))})),v=function(e){return e},b=o.forwardRef;void 0===b&&(b=v);var y=b((function(e,t){var n=e["aria-current"],a=void 0===n?"page":n,i=e.activeClassName,c=void 0===i?"active":i,f=e.activeStyle,m=e.className,g=e.exact,y=e.isActive,w=e.location,k=e.sensitive,E=e.strict,S=e.style,x=e.to,C=e.innerRef,_=(0,s.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,u.Z)(!1);var n=w||e.location,i=p(d(x,n),n),s=i.pathname,T=s&&s.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),A=T?(0,r.LX)(n.pathname,{path:T,exact:g,sensitive:k,strict:E}):null,L=!!(y?y(A,n):A),R="function"==typeof m?m(L):m,P="function"==typeof S?S(L):S;L&&(R=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(R,c),P=(0,l.Z)({},P,f));var N=(0,l.Z)({"aria-current":L&&a||null,className:R,style:P,to:i},_);return v!==b?N.ref=t||C:N.innerRef=C,o.createElement(h,N)}))}))},6550:(e,t,n)=>{"use strict";n.d(t,{AW:()=>x,F0:()=>w,LX:()=>S,TH:()=>O,k6:()=>N,rs:()=>R,s6:()=>y});var r=n(5068),a=n(7294),o=n(5697),i=n.n(o),l=n(9318),s=n(8776),u=n(7462),c=n(9658),d=n.n(c),p=(n(9864),n(3366)),f=(n(8679),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};function g(e){var t=[];return{on:function(e){t.push(e)},off:function(e){t=t.filter((function(t){return t!==e}))},get:function(){return e},set:function(n,r){e=n,t.forEach((function(t){return t(e,r)}))}}}var h=a.createContext||function(e,t){var n,o,l="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",s=function(e){function n(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).emitter=g(t.props.value),t}(0,r.Z)(n,e);var a=n.prototype;return a.getChildContext=function(){var e;return(e={})[l]=this.emitter,e},a.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,a=e.value;((o=r)===(i=a)?0!==o||1/o==1/i:o!=o&&i!=i)?n=0:(n="function"==typeof t?t(r,a):f,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,i},a.render=function(){return this.props.children},n}(a.Component);s.childContextTypes=((n={})[l]=i().object.isRequired,n);var u=function(t){function n(){for(var e,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(e=t.call.apply(t,[this].concat(r))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}(0,r.Z)(n,t);var a=n.prototype;return a.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?f:t},a.componentDidMount=function(){this.context[l]&&this.context[l].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?f:e},a.componentWillUnmount=function(){this.context[l]&&this.context[l].off(this.onUpdate)},a.getValue=function(){return this.context[l]?this.context[l].get():e},a.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(a.Component);return u.contextTypes=((o={})[l]=i().object,o),{Provider:s,Consumer:u}},v=function(e){var t=h();return t.displayName=e,t},b=v("Router-History"),y=v("Router"),w=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,r.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return a.createElement(y.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},a.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(a.Component);a.Component;a.Component;var k={},E=0;function S(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,a=n.exact,o=void 0!==a&&a,i=n.strict,l=void 0!==i&&i,s=n.sensitive,u=void 0!==s&&s;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=k[n]||(k[n]={});if(r[e])return r[e];var a=[],o={regexp:d()(e,a,t),keys:a};return E<1e4&&(r[e]=o,E++),o}(n,{end:o,strict:l,sensitive:u}),a=r.regexp,i=r.keys,s=a.exec(e);if(!s)return null;var c=s[0],p=s.slice(1),f=e===c;return o&&!f?null:{path:n,url:"/"===n&&""===c?"/":c,isExact:f,params:i.reduce((function(e,t,n){return e[t.name]=p[n],e}),{})}}),null)}var x=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(y.Consumer,null,(function(t){t||(0,s.Z)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?S(n.pathname,e.props):t.match,o=(0,u.Z)({},t,{location:n,match:r}),i=e.props,l=i.children,c=i.component,d=i.render;return Array.isArray(l)&&function(e){return 0===a.Children.count(e)}(l)&&(l=null),a.createElement(y.Provider,{value:o},o.match?l?"function"==typeof l?l(o):l:c?a.createElement(c,o):d?d(o):null:"function"==typeof l?l(o):null)}))},t}(a.Component);function C(e){return"/"===e.charAt(0)?e:"/"+e}function _(e,t){if(!e)return t;var n=C(e);return 0!==t.pathname.indexOf(n)?t:(0,u.Z)({},t,{pathname:t.pathname.substr(n.length)})}function T(e){return"string"==typeof e?e:(0,l.Ep)(e)}function A(e){return function(){(0,s.Z)(!1)}}function L(){}a.Component;var R=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(y.Consumer,null,(function(t){t||(0,s.Z)(!1);var n,r,o=e.props.location||t.location;return a.Children.forEach(e.props.children,(function(e){if(null==r&&a.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?S(o.pathname,(0,u.Z)({},e.props,{path:i})):t.match}})),r?a.cloneElement(n,{location:o,computedMatch:r}):null}))},t}(a.Component);var P=a.useContext;function N(){return P(b)}function O(){return P(y).location}},9658:(e,t,n)=>{var r=n(5826);e.exports=f,e.exports.parse=o,e.exports.compile=function(e,t){return l(o(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=p;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,l="",c=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],p=n[1],f=n.index;if(l+=e.slice(i,f),i=f+d.length,p)l+=p[1];else{var m=e[i],g=n[2],h=n[3],v=n[4],b=n[5],y=n[6],w=n[7];l&&(r.push(l),l="");var k=null!=g&&null!=m&&m!==g,E="+"===y||"*"===y,S="?"===y||"*"===y,x=n[2]||c,C=v||b;r.push({name:h||o++,prefix:g||"",delimiter:x,optional:S,repeat:E,partial:k,asterisk:!!w,pattern:C?u(C):w?".*":"[^"+s(x)+"]+?"})}}return i<e.length&&(l+=e.substr(i)),l&&r.push(l),r}function i(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function l(e,t){for(var n=new Array(e.length),a=0;a<e.length;a++)"object"==typeof e[a]&&(n[a]=new RegExp("^(?:"+e[a].pattern+")$",d(t)));return function(t,a){for(var o="",l=t||{},s=(a||{}).pretty?i:encodeURIComponent,u=0;u<e.length;u++){var c=e[u];if("string"!=typeof c){var d,p=l[c.name];if(null==p){if(c.optional){c.partial&&(o+=c.prefix);continue}throw new TypeError('Expected "'+c.name+'" to be defined')}if(r(p)){if(!c.repeat)throw new TypeError('Expected "'+c.name+'" to not repeat, but received `'+JSON.stringify(p)+"`");if(0===p.length){if(c.optional)continue;throw new TypeError('Expected "'+c.name+'" to not be empty')}for(var f=0;f<p.length;f++){if(d=s(p[f]),!n[u].test(d))throw new TypeError('Expected all "'+c.name+'" to match "'+c.pattern+'", but received `'+JSON.stringify(d)+"`");o+=(0===f?c.prefix:c.delimiter)+d}}else{if(d=c.asterisk?encodeURI(p).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):s(p),!n[u].test(d))throw new TypeError('Expected "'+c.name+'" to match "'+c.pattern+'", but received "'+d+'"');o+=c.prefix+d}}else o+=c}return o}}function s(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function u(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function c(e,t){return e.keys=t,e}function d(e){return e&&e.sensitive?"":"i"}function p(e,t,n){r(t)||(n=t||n,t=[]);for(var a=(n=n||{}).strict,o=!1!==n.end,i="",l=0;l<e.length;l++){var u=e[l];if("string"==typeof u)i+=s(u);else{var p=s(u.prefix),f="(?:"+u.pattern+")";t.push(u),u.repeat&&(f+="(?:"+p+f+")*"),i+=f=u.optional?u.partial?p+"("+f+")?":"(?:"+p+"("+f+"))?":p+"("+f+")"}}var m=s(n.delimiter||"/"),g=i.slice(-m.length)===m;return a||(i=(g?i.slice(0,-m.length):i)+"(?:"+m+"(?=$))?"),i+=o?"$":a&&g?"":"(?="+m+"|$)",c(new RegExp("^"+i,d(n)),t)}function f(e,t,n){return r(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return c(e,t)}(e,t):r(e)?function(e,t,n){for(var r=[],a=0;a<e.length;a++)r.push(f(e[a],t,n).source);return c(new RegExp("(?:"+r.join("|")+")",d(n)),t)}(e,t,n):function(e,t,n){return p(o(e,n),t,n)}(e,t,n)}},2408:(e,t,n)=>{"use strict";var r=n(7418),a=60103,o=60106;t.Fragment=60107,t.StrictMode=60108,t.Profiler=60114;var i=60109,l=60110,s=60112;t.Suspense=60113;var u=60115,c=60116;if("function"==typeof Symbol&&Symbol.for){var d=Symbol.for;a=d("react.element"),o=d("react.portal"),t.Fragment=d("react.fragment"),t.StrictMode=d("react.strict_mode"),t.Profiler=d("react.profiler"),i=d("react.provider"),l=d("react.context"),s=d("react.forward_ref"),t.Suspense=d("react.suspense"),u=d("react.memo"),c=d("react.lazy")}var p="function"==typeof Symbol&&Symbol.iterator;function f(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g={};function h(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}function v(){}function b(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}h.prototype.isReactComponent={},h.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(f(85));this.updater.enqueueSetState(this,e,t,"setState")},h.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},v.prototype=h.prototype;var y=b.prototype=new v;y.constructor=b,r(y,h.prototype),y.isPureReactComponent=!0;var w={current:null},k=Object.prototype.hasOwnProperty,E={key:!0,ref:!0,__self:!0,__source:!0};function S(e,t,n){var r,o={},i=null,l=null;if(null!=t)for(r in void 0!==t.ref&&(l=t.ref),void 0!==t.key&&(i=""+t.key),t)k.call(t,r)&&!E.hasOwnProperty(r)&&(o[r]=t[r]);var s=arguments.length-2;if(1===s)o.children=n;else if(1<s){for(var u=Array(s),c=0;c<s;c++)u[c]=arguments[c+2];o.children=u}if(e&&e.defaultProps)for(r in s=e.defaultProps)void 0===o[r]&&(o[r]=s[r]);return{$$typeof:a,type:e,key:i,ref:l,props:o,_owner:w.current}}function x(e){return"object"==typeof e&&null!==e&&e.$$typeof===a}var C=/\/+/g;function _(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function T(e,t,n,r,i){var l=typeof e;"undefined"!==l&&"boolean"!==l||(e=null);var s=!1;if(null===e)s=!0;else switch(l){case"string":case"number":s=!0;break;case"object":switch(e.$$typeof){case a:case o:s=!0}}if(s)return i=i(s=e),e=""===r?"."+_(s,0):r,Array.isArray(i)?(n="",null!=e&&(n=e.replace(C,"$&/")+"/"),T(i,t,n,"",(function(e){return e}))):null!=i&&(x(i)&&(i=function(e,t){return{$$typeof:a,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(i,n+(!i.key||s&&s.key===i.key?"":(""+i.key).replace(C,"$&/")+"/")+e)),t.push(i)),1;if(s=0,r=""===r?".":r+":",Array.isArray(e))for(var u=0;u<e.length;u++){var c=r+_(l=e[u],u);s+=T(l,t,n,c,i)}else if(c=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=p&&e[p]||e["@@iterator"])?e:null}(e),"function"==typeof c)for(e=c.call(e),u=0;!(l=e.next()).done;)s+=T(l=l.value,t,n,c=r+_(l,u++),i);else if("object"===l)throw t=""+e,Error(f(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t));return s}function A(e,t,n){if(null==e)return e;var r=[],a=0;return T(e,r,"","",(function(e){return t.call(n,e,a++)})),r}function L(e){if(-1===e._status){var t=e._result;t=t(),e._status=0,e._result=t,t.then((function(t){0===e._status&&(t=t.default,e._status=1,e._result=t)}),(function(t){0===e._status&&(e._status=2,e._result=t)}))}if(1===e._status)return e._result;throw e._result}var R={current:null};function P(){var e=R.current;if(null===e)throw Error(f(321));return e}var N={ReactCurrentDispatcher:R,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:w,IsSomeRendererActing:{current:!1},assign:r};t.Children={map:A,forEach:function(e,t,n){A(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return A(e,(function(){t++})),t},toArray:function(e){return A(e,(function(e){return e}))||[]},only:function(e){if(!x(e))throw Error(f(143));return e}},t.Component=h,t.PureComponent=b,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=N,t.cloneElement=function(e,t,n){if(null==e)throw Error(f(267,e));var o=r({},e.props),i=e.key,l=e.ref,s=e._owner;if(null!=t){if(void 0!==t.ref&&(l=t.ref,s=w.current),void 0!==t.key&&(i=""+t.key),e.type&&e.type.defaultProps)var u=e.type.defaultProps;for(c in t)k.call(t,c)&&!E.hasOwnProperty(c)&&(o[c]=void 0===t[c]&&void 0!==u?u[c]:t[c])}var c=arguments.length-2;if(1===c)o.children=n;else if(1<c){u=Array(c);for(var d=0;d<c;d++)u[d]=arguments[d+2];o.children=u}return{$$typeof:a,type:e.type,key:i,ref:l,props:o,_owner:s}},t.createContext=function(e,t){return void 0===t&&(t=null),(e={$$typeof:l,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:i,_context:e},e.Consumer=e},t.createElement=S,t.createFactory=function(e){var t=S.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:s,render:e}},t.isValidElement=x,t.lazy=function(e){return{$$typeof:c,_payload:{_status:-1,_result:e},_init:L}},t.memo=function(e,t){return{$$typeof:u,type:e,compare:void 0===t?null:t}},t.useCallback=function(e,t){return P().useCallback(e,t)},t.useContext=function(e,t){return P().useContext(e,t)},t.useDebugValue=function(){},t.useEffect=function(e,t){return P().useEffect(e,t)},t.useImperativeHandle=function(e,t,n){return P().useImperativeHandle(e,t,n)},t.useLayoutEffect=function(e,t){return P().useLayoutEffect(e,t)},t.useMemo=function(e,t){return P().useMemo(e,t)},t.useReducer=function(e,t,n){return P().useReducer(e,t,n)},t.useRef=function(e){return P().useRef(e)},t.useState=function(e){return P().useState(e)},t.version="17.0.2"},7294:(e,t,n)=>{"use strict";e.exports=n(2408)},53:(e,t)=>{"use strict";var n,r,a,o;if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;t.unstable_now=function(){return i.now()}}else{var l=Date,s=l.now();t.unstable_now=function(){return l.now()-s}}if("undefined"==typeof window||"function"!=typeof MessageChannel){var u=null,c=null,d=function(){if(null!==u)try{var e=t.unstable_now();u(!0,e),u=null}catch(n){throw setTimeout(d,0),n}};n=function(e){null!==u?setTimeout(n,0,e):(u=e,setTimeout(d,0))},r=function(e,t){c=setTimeout(e,t)},a=function(){clearTimeout(c)},t.unstable_shouldYield=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var p=window.setTimeout,f=window.clearTimeout;if("undefined"!=typeof console){var m=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),"function"!=typeof m&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")}var g=!1,h=null,v=-1,b=5,y=0;t.unstable_shouldYield=function(){return t.unstable_now()>=y},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):b=0<e?Math.floor(1e3/e):5};var w=new MessageChannel,k=w.port2;w.port1.onmessage=function(){if(null!==h){var e=t.unstable_now();y=e+b;try{h(!0,e)?k.postMessage(null):(g=!1,h=null)}catch(n){throw k.postMessage(null),n}}else g=!1},n=function(e){h=e,g||(g=!0,k.postMessage(null))},r=function(e,n){v=p((function(){e(t.unstable_now())}),n)},a=function(){f(v),v=-1}}function E(e,t){var n=e.length;e.push(t);e:for(;;){var r=n-1>>>1,a=e[r];if(!(void 0!==a&&0<C(a,t)))break e;e[r]=t,e[n]=a,n=r}}function S(e){return void 0===(e=e[0])?null:e}function x(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,a=e.length;r<a;){var o=2*(r+1)-1,i=e[o],l=o+1,s=e[l];if(void 0!==i&&0>C(i,n))void 0!==s&&0>C(s,i)?(e[r]=s,e[l]=n,r=l):(e[r]=i,e[o]=n,r=o);else{if(!(void 0!==s&&0>C(s,n)))break e;e[r]=s,e[l]=n,r=l}}}return t}return null}function C(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var _=[],T=[],A=1,L=null,R=3,P=!1,N=!1,O=!1;function I(e){for(var t=S(T);null!==t;){if(null===t.callback)x(T);else{if(!(t.startTime<=e))break;x(T),t.sortIndex=t.expirationTime,E(_,t)}t=S(T)}}function D(e){if(O=!1,I(e),!N)if(null!==S(_))N=!0,n(M);else{var t=S(T);null!==t&&r(D,t.startTime-e)}}function M(e,n){N=!1,O&&(O=!1,a()),P=!0;var o=R;try{for(I(n),L=S(_);null!==L&&(!(L.expirationTime>n)||e&&!t.unstable_shouldYield());){var i=L.callback;if("function"==typeof i){L.callback=null,R=L.priorityLevel;var l=i(L.expirationTime<=n);n=t.unstable_now(),"function"==typeof l?L.callback=l:L===S(_)&&x(_),I(n)}else x(_);L=S(_)}if(null!==L)var s=!0;else{var u=S(T);null!==u&&r(D,u.startTime-n),s=!1}return s}finally{L=null,R=o,P=!1}}var F=o;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){N||P||(N=!0,n(M))},t.unstable_getCurrentPriorityLevel=function(){return R},t.unstable_getFirstCallbackNode=function(){return S(_)},t.unstable_next=function(e){switch(R){case 1:case 2:case 3:var t=3;break;default:t=R}var n=R;R=t;try{return e()}finally{R=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=F,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=R;R=e;try{return t()}finally{R=n}},t.unstable_scheduleCallback=function(e,o,i){var l=t.unstable_now();switch("object"==typeof i&&null!==i?i="number"==typeof(i=i.delay)&&0<i?l+i:l:i=l,e){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return e={id:A++,callback:o,priorityLevel:e,startTime:i,expirationTime:s=i+s,sortIndex:-1},i>l?(e.sortIndex=i,E(T,e),null===S(_)&&e===S(T)&&(O?a():O=!0,r(D,i-l))):(e.sortIndex=s,E(_,e),N||P||(N=!0,n(M))),e},t.unstable_wrapCallback=function(e){var t=R;return function(){var n=R;R=t;try{return e.apply(this,arguments)}finally{R=n}}}},3840:(e,t,n)=>{"use strict";e.exports=n(53)},6774:e=>{e.exports=function(e,t,n,r){var a=n?n.call(r,e,t):void 0;if(void 0!==a)return!!a;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),i=Object.keys(t);if(o.length!==i.length)return!1;for(var l=Object.prototype.hasOwnProperty.bind(t),s=0;s<o.length;s++){var u=o[s];if(!l(u))return!1;var c=e[u],d=t[u];if(!1===(a=n?n.call(r,c,d,u):void 0)||void 0===a&&c!==d)return!1}return!0}},6809:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={title:"Rollkit",tagline:"A modular framework for rollups",url:"https://rollkit.dev",baseUrl:"/pr-preview/pr-192/",onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",favicon:"img/favicon.ico",trailingSlash:!0,organizationName:"rollkit",projectName:"docs",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},scripts:[{src:"https://plausible.celestia.org/js/plausible.js",defer:!0,"data-domain":"rollkit.dev"}],presets:[["classic",{docs:{sidebarPath:"/home/runner/work/docs/docs/sidebars.js",editUrl:"https://github.com/rollkit/docs/tree/main/"},blog:{showReadingTime:!0,editUrl:"https://github.com/rollkit/docs/tree/main/"},theme:{customCss:"/home/runner/work/docs/docs/src/css/custom.css"}}]],themeConfig:{navbar:{logo:{alt:"Rollkit",src:"img/rollkit-blk.svg",srcDark:"img/rollkit-wht.svg"},items:[{to:"/docs/intro",position:"left",label:"Docs"},{to:"/blog",position:"right",label:"Blog"},{type:"dropdown",label:"Community",position:"right",items:[{label:"Telegram",href:"https://t.me/rollkit"},{label:"Twitter",href:"https://twitter.com/Rollkitdev"},{label:"Google Calendar",href:"https://calendar.google.com/calendar/u/0/r?cid=c_11a8d6a470ca9c07b131ab1ea213ac124a3061a9d6986bb208d88afbcc4bb3d2@group.calendar.google.com"},{label:"YouTube",href:"https://www.youtube.com/@RollkitDev"}]},{href:"https://github.com/rollkit",label:"GitHub",position:"right"}],hideOnScroll:!1},footer:{style:"dark",copyright:"Copyright \xa9 2023 Rollkit",links:[]},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:[],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},colorMode:{defaultMode:"dark",disableSwitch:!1,respectPrefersColorScheme:!0},image:"img/Rollkit-og.png",docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},plugins:[],themes:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{mermaid:!1}}},7462:(e,t,n)=>{"use strict";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(this,arguments)}n.d(t,{Z:()=>r})},5068:(e,t,n)=>{"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>a})},3366:(e,t,n)=>{"use strict";function r(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}n.d(t,{Z:()=>r})},8776:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r="Invariant failed";function a(e,t){if(!e)throw new Error(r)}},7529:e=>{"use strict";e.exports={}},6887:e=>{"use strict";e.exports=JSON.parse('{"/pr-preview/pr-192/blog/-65f":{"__comp":"a6aa9e1f","__context":{"plugin":"1c091541"},"sidebar":"814f3328","items":[{"content":"32f16e92"},{"content":"7d4011c1"},{"content":"84d3f767"}],"metadata":"21d57c30"},"/pr-preview/pr-192/blog/archive/-e68":{"__comp":"9e4087bc","__context":{"plugin":"1c091541"},"archive":"80930d5b"},"/pr-preview/pr-192/blog/introducing-rollkit/-aa9":{"__comp":"ccc49370","__context":{"plugin":"1c091541"},"sidebar":"814f3328","content":"33efe628"},"/pr-preview/pr-192/blog/lets-roll-community-call/-7ab":{"__comp":"ccc49370","__context":{"plugin":"1c091541"},"sidebar":"814f3328","content":"7aa79d9e"},"/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/-b75":{"__comp":"ccc49370","__context":{"plugin":"1c091541"},"sidebar":"814f3328","content":"ddc2e5d7"},"/pr-preview/pr-192/blog/tags/-b14":{"__comp":"01a85c17","__context":{"plugin":"1c091541"},"sidebar":"814f3328","tags":"4650ee82"},"/pr-preview/pr-192/blog/tags/bitcoin/-fd3":{"__comp":"6875c492","__context":{"plugin":"1c091541"},"sidebar":"814f3328","items":[{"content":"7d4011c1"}],"tag":"9434eb16","listMetadata":"b7833b35"},"/pr-preview/pr-192/blog/tags/celestia/-038":{"__comp":"6875c492","__context":{"plugin":"1c091541"},"sidebar":"814f3328","items":[{"content":"84d3f767"}],"tag":"9064f397","listMetadata":"73f84a4a"},"/pr-preview/pr-192/blog/tags/rollkit/-0e4":{"__comp":"6875c492","__context":{"plugin":"1c091541"},"sidebar":"814f3328","items":[{"content":"32f16e92"},{"content":"7d4011c1"},{"content":"84d3f767"}],"tag":"85430e88","listMetadata":"17010a1c"},"/pr-preview/pr-192/docs/-bff":{"__comp":"1be78505","__context":{"plugin":"247783bb"},"versionMetadata":"935f2afb"},"/pr-preview/pr-192/docs/category/advanced/-b1f":{"__comp":"14eb3368","categoryGeneratedIndex":"4789b10c"},"/pr-preview/pr-192/docs/category/beginner/-e28":{"__comp":"14eb3368","categoryGeneratedIndex":"feb3943e"},"/pr-preview/pr-192/docs/category/intermediate/-27f":{"__comp":"14eb3368","categoryGeneratedIndex":"e8a90596"},"/pr-preview/pr-192/docs/category/tutorials/-387":{"__comp":"14eb3368","categoryGeneratedIndex":"48bdfc14"},"/pr-preview/pr-192/docs/intro/-1ef":{"__comp":"17896441","content":"0e384e19"},"/pr-preview/pr-192/docs/rollkit-stack/-8e3":{"__comp":"17896441","content":"c463304d"},"/pr-preview/pr-192/docs/transaction-flow/-957":{"__comp":"17896441","content":"dbc9f6d7"},"/pr-preview/pr-192/docs/tutorials/bitcoin/-ce8":{"__comp":"17896441","content":"94d5b9f3"},"/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/-59b":{"__comp":"17896441","content":"cd10b72d"},"/pr-preview/pr-192/docs/tutorials/cosmwasm/-67c":{"__comp":"17896441","content":"ea3e41d5"},"/pr-preview/pr-192/docs/tutorials/ethermint/-899":{"__comp":"17896441","content":"8f6681fc"},"/pr-preview/pr-192/docs/tutorials/gm-world-frontend/-6ce":{"__comp":"17896441","content":"2952c598"},"/pr-preview/pr-192/docs/tutorials/gm-world/-58f":{"__comp":"17896441","content":"53f25740"},"/pr-preview/pr-192/docs/tutorials/recipe-book/-591":{"__comp":"17896441","content":"be631169"},"/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/-b0a":{"__comp":"17896441","content":"2e006f0d"},"/pr-preview/pr-192/docs/tutorials/wordle/-2fa":{"__comp":"17896441","content":"c7d6d209"},"/pr-preview/pr-192/-289":{"__comp":"1df93b7f","__context":{"plugin":"a7434565"},"config":"5e9f5e1a"}}')}},e=>{e.O(0,[532],(()=>{return t=9383,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/pr-preview/pr-192/assets/js/main.b1788751.js.LICENSE.txt b/pr-preview/pr-192/assets/js/main.b1788751.js.LICENSE.txt deleted file mode 100644 index 6e08db297..000000000 --- a/pr-preview/pr-192/assets/js/main.b1788751.js.LICENSE.txt +++ /dev/null @@ -1,53 +0,0 @@ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ - -/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress - * @license MIT */ - -/** - * Prism: Lightweight, robust, elegant syntax highlighting - * - * @license MIT <https://opensource.org/licenses/MIT> - * @author Lea Verou <https://lea.verou.me> - * @namespace - * @public - */ - -/** @license React v0.20.2 - * scheduler.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v16.13.1 - * react-is.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v17.0.2 - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v17.0.2 - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ diff --git a/pr-preview/pr-192/assets/js/runtime~main.288f2b9c.js b/pr-preview/pr-192/assets/js/runtime~main.288f2b9c.js deleted file mode 100644 index 2658d1b3c..000000000 --- a/pr-preview/pr-192/assets/js/runtime~main.288f2b9c.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var e,t,r,d,a,c={},f={};function o(e){var t=f[e];if(void 0!==t)return t.exports;var r=f[e]={id:e,loaded:!1,exports:{}};return c[e].call(r.exports,r,r.exports,o),r.loaded=!0,r.exports}o.m=c,o.c=f,e=[],o.O=(t,r,d,a)=>{if(!r){var c=1/0;for(i=0;i<e.length;i++){r=e[i][0],d=e[i][1],a=e[i][2];for(var f=!0,n=0;n<r.length;n++)(!1&a||c>=a)&&Object.keys(o.O).every((e=>o.O[e](r[n])))?r.splice(n--,1):(f=!1,a<c&&(c=a));if(f){e.splice(i--,1);var b=d();void 0!==b&&(t=b)}}return t}a=a||0;for(var i=e.length;i>0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[r,d,a]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,o.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var a=Object.create(null);o.r(a);var c={};t=t||[null,r({}),r([]),r(r)];for(var f=2&d&&e;"object"==typeof f&&!~t.indexOf(f);f=r(f))Object.getOwnPropertyNames(f).forEach((t=>c[t]=()=>e[t]));return c.default=()=>e,o.d(a,c),a},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((t,r)=>(o.f[r](e,t),t)),[])),o.u=e=>"assets/js/"+({53:"935f2afb",863:"84d3f767",1074:"dbc9f6d7",1392:"2e006f0d",2193:"c463304d",2535:"814f3328",2844:"7d4011c1",3089:"a6aa9e1f",3237:"1df93b7f",3265:"94d5b9f3",3553:"4789b10c",3608:"9e4087bc",4013:"01a85c17",4500:"feb3943e",5191:"8f6681fc",5326:"9064f397",5331:"7aa79d9e",5842:"ea3e41d5",5986:"e8a90596",6103:"ccc49370",6105:"cd10b72d",6592:"21d57c30",6688:"33efe628",7087:"2952c598",7164:"b7833b35",7238:"4650ee82",7284:"17010a1c",7645:"a7434565",7819:"48bdfc14",7918:"17896441",8235:"be631169",8271:"1c091541",8347:"80930d5b",8362:"9434eb16",8610:"6875c492",8696:"c7d6d209",8714:"ddc2e5d7",8757:"32f16e92",9048:"53f25740",9334:"247783bb",9492:"73f84a4a",9514:"1be78505",9643:"85430e88",9671:"0e384e19",9817:"14eb3368"}[e]||e)+"."+{53:"9deca9a6",863:"6e19ef29",1074:"98fdef6e",1392:"d207a387",2193:"ea019477",2535:"9d5272cf",2844:"c36b3498",3089:"845cad8c",3237:"dc76c62a",3265:"6236b83d",3553:"db037f9d",3608:"ded25007",4013:"80cbea07",4500:"7b2bdf60",4972:"4136cbbb",5191:"2d347811",5326:"563e2664",5331:"bfc0122e",5842:"ec8db3d9",5986:"85177f7f",6048:"4ec4ba27",6103:"9164d42e",6105:"4205b928",6592:"5ce19e6b",6688:"2b1da1df",7036:"6d9b6d0a",7087:"58be34ab",7164:"fbe5f020",7238:"3692f0e3",7284:"8e4a3039",7645:"8a3a8041",7819:"09373ca8",7918:"88df801a",8235:"f4545f2b",8271:"60b718c6",8347:"dd96b7fe",8362:"e6ae1522",8610:"f37b7b5c",8696:"c1f645dd",8714:"2e885599",8757:"0783d6a4",9048:"92622228",9334:"dadfb5a6",9492:"4c420f96",9514:"fa749a32",9643:"6b8aacab",9671:"f393c369",9817:"9bfa4e30"}[e]+".js",o.miniCssF=e=>{},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),d={},a="docs:",o.l=(e,t,r,c)=>{if(d[e])d[e].push(t);else{var f,n;if(void 0!==r)for(var b=document.getElementsByTagName("script"),i=0;i<b.length;i++){var u=b[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==a+r){f=u;break}}f||(n=!0,(f=document.createElement("script")).charset="utf-8",f.timeout=120,o.nc&&f.setAttribute("nonce",o.nc),f.setAttribute("data-webpack",a+r),f.src=e),d[e]=[t];var l=(t,r)=>{f.onerror=f.onload=null,clearTimeout(s);var a=d[e];if(delete d[e],f.parentNode&&f.parentNode.removeChild(f),a&&a.forEach((e=>e(r))),t)return t(r)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:f}),12e4);f.onerror=l.bind(null,f.onerror),f.onload=l.bind(null,f.onload),n&&document.head.appendChild(f)}},o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.p="/pr-preview/pr-192/",o.gca=function(e){return e={17896441:"7918","935f2afb":"53","84d3f767":"863",dbc9f6d7:"1074","2e006f0d":"1392",c463304d:"2193","814f3328":"2535","7d4011c1":"2844",a6aa9e1f:"3089","1df93b7f":"3237","94d5b9f3":"3265","4789b10c":"3553","9e4087bc":"3608","01a85c17":"4013",feb3943e:"4500","8f6681fc":"5191","9064f397":"5326","7aa79d9e":"5331",ea3e41d5:"5842",e8a90596:"5986",ccc49370:"6103",cd10b72d:"6105","21d57c30":"6592","33efe628":"6688","2952c598":"7087",b7833b35:"7164","4650ee82":"7238","17010a1c":"7284",a7434565:"7645","48bdfc14":"7819",be631169:"8235","1c091541":"8271","80930d5b":"8347","9434eb16":"8362","6875c492":"8610",c7d6d209:"8696",ddc2e5d7:"8714","32f16e92":"8757","53f25740":"9048","247783bb":"9334","73f84a4a":"9492","1be78505":"9514","85430e88":"9643","0e384e19":"9671","14eb3368":"9817"}[e]||e,o.p+o.u(e)},(()=>{var e={1303:0,532:0};o.f.j=(t,r)=>{var d=o.o(e,t)?e[t]:void 0;if(0!==d)if(d)r.push(d[2]);else if(/^(1303|532)$/.test(t))e[t]=0;else{var a=new Promise(((r,a)=>d=e[t]=[r,a]));r.push(d[2]=a);var c=o.p+o.u(t),f=new Error;o.l(c,(r=>{if(o.o(e,t)&&(0!==(d=e[t])&&(e[t]=void 0),d)){var a=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;f.message="Loading chunk "+t+" failed.\n("+a+": "+c+")",f.name="ChunkLoadError",f.type=a,f.request=c,d[1](f)}}),"chunk-"+t,t)}},o.O.j=t=>0===e[t];var t=(t,r)=>{var d,a,c=r[0],f=r[1],n=r[2],b=0;if(c.some((t=>0!==e[t]))){for(d in f)o.o(f,d)&&(o.m[d]=f[d]);if(n)var i=n(o)}for(t&&t(r);b<c.length;b++)a=c[b],o.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return o.O(i)},r=self.webpackChunkdocs=self.webpackChunkdocs||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})()})(); \ No newline at end of file diff --git a/pr-preview/pr-192/blog/archive/index.html b/pr-preview/pr-192/blog/archive/index.html deleted file mode 100644 index 7b5dc3f9c..000000000 --- a/pr-preview/pr-192/blog/archive/index.html +++ /dev/null @@ -1,21 +0,0 @@ -<!doctype html> -<html lang="en" dir="ltr" class="plugin-blog plugin-id-default"> -<head> -<meta charset="UTF-8"> -<meta name="generator" content="Docusaurus v2.2.0"> -<title data-rh="true">Archive | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/atom.xml b/pr-preview/pr-192/blog/atom.xml deleted file mode 100644 index f72fbd334..000000000 --- a/pr-preview/pr-192/blog/atom.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - https://rollkit.dev/pr-preview/pr-192/blog - Rollkit Blog - 2023-03-08T00:00:00.000Z - https://github.com/jpmonette/feed - - Rollkit Blog - https://rollkit.dev/pr-preview/pr-192/img/favicon.ico - - <![CDATA[Let's Roll - Rollkit's community call]]> - lets-roll-community-call - - 2023-03-08T00:00:00.000Z - - Rollkit blog cover

Last Sunday, we released the first research implementation that allows Rollkit rollups to use Bitcoin for data availability.

This announcement has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They’re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.

We believe that there’s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.

That’s why we’re happy to announce that we’re launching a Rollkit’s community call: Let’s Roll.

TL;DR

  • Rollkit is launching its community call, Let’s Roll. You can subscribe to the community calendar here

  • The first meeting is scheduled on Zoom for March 21, 2023, 6pm CET(12pm EST, 9am PST).

  • Builders using Rollkit can now present their projects at Let’s Roll. Reach out to us on Telegram

Just merge it

Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good.

However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit’s development.

By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community.

One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.

Our promise, as core contributors, is to do our best to make “just merge it” a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated.

That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.

What is Let’s Roll?

Let's Roll is a dynamic community-focused meeting that brings together all Rollkit’s contributors to drive the innovation and development of Rollkit.

This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.

Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.

The meeting will be hosted on Zoom. Subscribe to the following Google calendar so that you can be notified of future community calls.

Conclusion

Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework. -With demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project.

We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.

So, join us, roll with us, and let's shape the future of rollup frameworks together.

]]>
- - Joseph Al-Chami - https://github.com/AlCJoseph - - -
- - <![CDATA[Sovereign rollups on Bitcoin with Rollkit]]> - sovereign-rollups-on-bitcoin - - 2023-03-05T00:00:00.000Z - - rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

]]>
- - Rollkit - https://github.com/rollkit - - - -
- - <![CDATA[Introducing Rollkit: a modular rollup framework]]> - introducing-rollkit - - 2023-02-21T00:00:00.000Z - - The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

]]>
- - Joseph Al-Chami - https://github.com/AlCJoseph - - - Alex Beckett - https://github.com/alex-beckett - - - -
-
\ No newline at end of file diff --git a/pr-preview/pr-192/blog/index.html b/pr-preview/pr-192/blog/index.html deleted file mode 100644 index 30dcdde14..000000000 --- a/pr-preview/pr-192/blog/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -Blog | Rollkit - - - - - - - - - -
-

· 4 min read

Rollkit blog cover

Last Sunday, we released the first research implementation that allows Rollkit rollups to use Bitcoin for data availability.

This announcement has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They’re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.

We believe that there’s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.

That’s why we’re happy to announce that we’re launching a Rollkit’s community call: Let’s Roll.

TL;DR

  • Rollkit is launching its community call, Let’s Roll. You can subscribe to the community calendar here

  • The first meeting is scheduled on Zoom for March 21, 2023, 6pm CET(12pm EST, 9am PST).

  • Builders using Rollkit can now present their projects at Let’s Roll. Reach out to us on Telegram

Just merge it

Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good.

However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit’s development.

By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community.

One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.

Our promise, as core contributors, is to do our best to make “just merge it” a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated.

That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.

What is Let’s Roll?

Let's Roll is a dynamic community-focused meeting that brings together all Rollkit’s contributors to drive the innovation and development of Rollkit.

This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.

Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.

The meeting will be hosted on Zoom. Subscribe to the following Google calendar so that you can be notified of future community calls.

Conclusion

Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework. -With demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project.

We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.

So, join us, roll with us, and let's shape the future of rollup frameworks together.

· 5 min read

rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

· 6 min read

The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/introducing-rollkit/index.html b/pr-preview/pr-192/blog/introducing-rollkit/index.html deleted file mode 100644 index aabfbe9f4..000000000 --- a/pr-preview/pr-192/blog/introducing-rollkit/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Introducing Rollkit: a modular rollup framework | Rollkit - - - - - - - - - -
-

Introducing Rollkit: a modular rollup framework

· 6 min read

The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/lets-roll-community-call/index.html b/pr-preview/pr-192/blog/lets-roll-community-call/index.html deleted file mode 100644 index 8827c0942..000000000 --- a/pr-preview/pr-192/blog/lets-roll-community-call/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -Let's Roll - Rollkit's community call | Rollkit - - - - - - - - - -
-

Let's Roll - Rollkit's community call

· 4 min read

Rollkit blog cover

Last Sunday, we released the first research implementation that allows Rollkit rollups to use Bitcoin for data availability.

This announcement has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They’re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.

We believe that there’s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.

That’s why we’re happy to announce that we’re launching a Rollkit’s community call: Let’s Roll.

TL;DR

  • Rollkit is launching its community call, Let’s Roll. You can subscribe to the community calendar here

  • The first meeting is scheduled on Zoom for March 21, 2023, 6pm CET(12pm EST, 9am PST).

  • Builders using Rollkit can now present their projects at Let’s Roll. Reach out to us on Telegram

Just merge it

Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good.

However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit’s development.

By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community.

One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.

Our promise, as core contributors, is to do our best to make “just merge it” a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated.

That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.

What is Let’s Roll?

Let's Roll is a dynamic community-focused meeting that brings together all Rollkit’s contributors to drive the innovation and development of Rollkit.

This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.

Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.

The meeting will be hosted on Zoom. Subscribe to the following Google calendar so that you can be notified of future community calls.

Conclusion

Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework. -With demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project.

We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.

So, join us, roll with us, and let's shape the future of rollup frameworks together.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/rss.xml b/pr-preview/pr-192/blog/rss.xml deleted file mode 100644 index d7fedc558..000000000 --- a/pr-preview/pr-192/blog/rss.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - Rollkit Blog - https://rollkit.dev/pr-preview/pr-192/blog - Rollkit Blog - Wed, 08 Mar 2023 00:00:00 GMT - https://validator.w3.org/feed/docs/rss2.html - https://github.com/jpmonette/feed - en - - <![CDATA[Let's Roll - Rollkit's community call]]> - https://rollkit.dev/pr-preview/pr-192/blog/lets-roll-community-call - lets-roll-community-call - Wed, 08 Mar 2023 00:00:00 GMT - - Rollkit blog cover

Last Sunday, we released the first research implementation that allows Rollkit rollups to use Bitcoin for data availability.

This announcement has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They’re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.

We believe that there’s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.

That’s why we’re happy to announce that we’re launching a Rollkit’s community call: Let’s Roll.

TL;DR

  • Rollkit is launching its community call, Let’s Roll. You can subscribe to the community calendar here

  • The first meeting is scheduled on Zoom for March 21, 2023, 6pm CET(12pm EST, 9am PST).

  • Builders using Rollkit can now present their projects at Let’s Roll. Reach out to us on Telegram

Just merge it

Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good.

However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit’s development.

By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community.

One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.

Our promise, as core contributors, is to do our best to make “just merge it” a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated.

That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.

What is Let’s Roll?

Let's Roll is a dynamic community-focused meeting that brings together all Rollkit’s contributors to drive the innovation and development of Rollkit.

This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.

Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.

The meeting will be hosted on Zoom. Subscribe to the following Google calendar so that you can be notified of future community calls.

Conclusion

Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework. -With demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project.

We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.

So, join us, roll with us, and let's shape the future of rollup frameworks together.

]]>
- Rollkit -
- - <![CDATA[Sovereign rollups on Bitcoin with Rollkit]]> - https://rollkit.dev/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin - sovereign-rollups-on-bitcoin - Sun, 05 Mar 2023 00:00:00 GMT - - rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

]]>
- Rollkit - Bitcoin -
- - <![CDATA[Introducing Rollkit: a modular rollup framework]]> - https://rollkit.dev/pr-preview/pr-192/blog/introducing-rollkit - introducing-rollkit - Tue, 21 Feb 2023 00:00:00 GMT - - The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

]]>
- Rollkit - Celestia -
-
-
\ No newline at end of file diff --git a/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/index.html b/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/index.html deleted file mode 100644 index bcd498050..000000000 --- a/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Sovereign rollups on Bitcoin with Rollkit | Rollkit - - - - - - - - - -
-

Sovereign rollups on Bitcoin with Rollkit

· 5 min read

rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/tags/bitcoin/index.html b/pr-preview/pr-192/blog/tags/bitcoin/index.html deleted file mode 100644 index c0512b5c3..000000000 --- a/pr-preview/pr-192/blog/tags/bitcoin/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -One post tagged with "Bitcoin" | Rollkit - - - - - - - - - -
-

One post tagged with "Bitcoin"

View All Tags

· 5 min read

rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/tags/celestia/index.html b/pr-preview/pr-192/blog/tags/celestia/index.html deleted file mode 100644 index bd85a86ef..000000000 --- a/pr-preview/pr-192/blog/tags/celestia/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -One post tagged with "Celestia" | Rollkit - - - - - - - - - -
-

One post tagged with "Celestia"

View All Tags

· 6 min read

The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/tags/index.html b/pr-preview/pr-192/blog/tags/index.html deleted file mode 100644 index 0bc6bd07a..000000000 --- a/pr-preview/pr-192/blog/tags/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Tags | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/blog/tags/rollkit/index.html b/pr-preview/pr-192/blog/tags/rollkit/index.html deleted file mode 100644 index 756667ae6..000000000 --- a/pr-preview/pr-192/blog/tags/rollkit/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -3 posts tagged with "Rollkit" | Rollkit - - - - - - - - - -
-

3 posts tagged with "Rollkit"

View All Tags

· 4 min read

Rollkit blog cover

Last Sunday, we released the first research implementation that allows Rollkit rollups to use Bitcoin for data availability.

This announcement has sparked a lot of curiosity and excitement in the community. Many developers are starting to imagine what the future of sovereign rollups could look like on Bitcoin and other data availability layers. They’re looking for ways to innovate using this integration, to replicate it on other layer 1 blockchains, to identify challenges and to suggest improvements.

We believe that there’s a lot of innovation to be done and a lot of challenges to be solved, and that together as a community, we can collaborate on building the future of rollup frameworks.

That’s why we’re happy to announce that we’re launching a Rollkit’s community call: Let’s Roll.

TL;DR

  • Rollkit is launching its community call, Let’s Roll. You can subscribe to the community calendar here

  • The first meeting is scheduled on Zoom for March 21, 2023, 6pm CET(12pm EST, 9am PST).

  • Builders using Rollkit can now present their projects at Let’s Roll. Reach out to us on Telegram

Just merge it

Rollup development is rapidly evolving, with new types of rollups such as sovereign and pessimistic rollups emerging, and with new possibilities of using layer 1-blockchains as data availability layers. Rollkit is at the forefront of the rollup movement offering a modular framework for rollups as an open-source public good.

However, Rollkit's true potential lies in its community of developers and users who bring their unique perspectives, skills, and expertise to the table. When Rollkit integrates a new data availability layer, its community members are best suited to improve this integration and use it in ways that truly benefit the community. Therefore, we invite developers from different communities and skill sets to join us and contribute to Rollkit’s development.

By contributing to Rollkit, we reduce fragmentation, duplicated features and bugs, and we ensure the continuous improvement of Rollkit. By doing that we forge a stronger and bigger community.

One framework is bigger than the sum of all its forks. Together we can build something for all developers and builders to easily use.

Our promise, as core contributors, is to do our best to make “just merge it” a reality. We strive to empower developers to contribute to Rollkit and ensure that their contributions are integrated.

That's why we believe it's time to bring our community together to share knowledge, collaborate on new ideas, and inspire each other to push the limits of what's possible with Rollkit.

What is Let’s Roll?

Let's Roll is a dynamic community-focused meeting that brings together all Rollkit’s contributors to drive the innovation and development of Rollkit.

This meeting serves as a platform for sharing knowledge, discussing the latest updates, and exploring new ideas. Rollkit's contributors will demonstrate the most recent features and advancements, while community members will have the chance to ask questions, provide feedback, and collaborate on new projects.

Building open source means encouraging collaboration and teamwork among all developers. Sharing code and ideas will help us build a better framework more efficiently.

The meeting will be hosted on Zoom. Subscribe to the following Google calendar so that you can be notified of future community calls.

Conclusion

Let's Roll is an exciting opportunity for the Rollkit community to come together, share ideas, and collaborate on the future of this powerful framework. -With demos of the latest developments, a discussion of the roadmap and vision, and a dedicated Q&A and feedback session, Let's Roll is an opportunity to stay informed and engaged with the project.

We invite everyone interested in Rollkit and rollup development to join us. Your feedback, ideas, and input are essential to the success of Rollkit, and we look forward to seeing what we can achieve together.

So, join us, roll with us, and let's shape the future of rollup frameworks together.

· 5 min read

rollkit-bitcoin

Last week, we introduced Rollkit, a modular framework for rollups. Today, we are proud to announce that Rollkit is the first rollup framework to support sovereign rollups on Bitcoin. An early research implementation allows Rollkit rollups to use Bitcoin for data availability.

Rollkit is opening the door for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and re-org resistance. With the new integration it is now possible to run the EVM on Bitcoin as a Rollkit sovereign rollup. Sovereign rollups on Bitcoin not only expand the possibilities for rollups, but also have the potential to help bootstrap a healthy blockspace fee market on Bitcoin, enabling a more sustainable security budget.

Tl;dr

  • Sovereign rollups using Bitcoin for data availability are now a reality with Rollkit’s new early research integration.
  • Follow along with a demo of the EVM running on Bitcoin as a sovereign Rollkit rollup.
  • The implementation was possible due to Bitcoin's Taproot upgrade and Ordinals' usage of Bitcoin for publishing arbitrary data.

Posting data on Bitcoin with Taproot

On Feb. 1, 2023, the Luxor mining pool mined the largest Bitcoin block (#774628) ever, approximately 4 MB. Most of the blockspace was used to inscribe a Taproot Wizards NFT with Ordinals, a project that implements NFTs on Bitcoin by publishing the image data on-chain.

Bitcoin NFTs use Taproot witnesses to inscribe arbitrary data, enabled by Bitcoin's Taproot upgrade. Taproot witnesses provide a slightly better payload-to-data ratio than SegWit transactions. A standard transaction can include up to around 390kB of arbitrary data while still passing through the public mempool. A non-standard transaction, included by a miner directly without passing through the mempool, can include close to 4MB of arbitrary data. In short, with SegWit, it became viable to post big blobs of data to the Bitcoin blockchain.

Since then, the usage of Ordinals for NFT inscriptions and Taproot utilization has kicked off. Eric Wall found that at the time of his tweet, posting data on Bitcoin was 7x cheaper than Ethereum. Now that there are thousands of inscriptions on Bitcoin, it has become clear that sovereign rollups and an ecosystem of dapps on Bitcoin could become a reality. The missing piece: a rollup framework for easily integrating Bitcoin as a data availability layer.

Integrating Bitcoin as a data availability layer into Rollkit

Rollkit is a modular framework for rollups, where developers can plug-in custom execution layers and data availability layers. Initially, Rollkit only supported Celestia as an option for data availability and consensus. Now, Bitcoin is an option, thanks to an early research implementation of a Bitcoin data availability module for Rollkit. In this case, sovereign rollups manage their own execution and settlement while offloading consensus and data availability to Bitcoin.

rollkit-bitcoin-rollup

How Rollkit posts data to Bitcoin

To write and read data on Bitcoin, we make use of Taproot transactions. To facilitate this, we implemented a Go package called bitcoin-da that provides a reader/writer interface to Bitcoin. For details of how the interface works and how it uses Taproot, see the specs. The package can be re-used by any project that wants to read or write data on Bitcoin.

Rollkit was built with modularity at its core. It has a data availability interface so that developers can simply implement specific methods to add a new data availability layer. To add a data availability layer, implementers need to satisfy the DataAvailabilityLayerClient interface which defines the behavior of the data availability client, and the BlockRetriever interface which defines how blocks can be synced. These interfaces live in the da package. The most important methods in these interfaces are SubmitBlock and RetrieveBlock for reading and writing the blocks.

After implementing the Taproot reader/writer interface for Bitcoin (bitcoin-da), adding it as a data availability module for Rollkit took less than a day. We mostly only had to implement the SubmitBlock and RetrieveBlocks functions for Rollkit to call the Read and Write methods in bitcoin-da.

rollkit-bitcoin-rollup-2

EVM on Bitcoin demo

Rollkit supports custom execution layers, including EVM, CosmWasm, or the Cosmos SDK. To test the integration, we used Rollkit to run the EVM (using Ethermint) as a sovereign rollup on a local Bitcoin test network. See below for a demo.

Conclusion

As we move towards a future where sovereign communities will form around different applications, asking them to incur the high cost and overhead of deploying a layer 1 blockchain to be sovereign is not sustainable. Sovereign rollups fix this by making it possible to deploy a sovereign chain that inherits the data availability and consensus of another layer 1 chain such as Bitcoin.

Our goal with Rollkit is to make it easy to build and customize rollups. We invite you to play around Rollkit and build sovereign rollups on Bitcoin, or customize Rollkit with different execution environments and data availability layers. For details on how to run Rollkit with the Bitcoin data availability module, see the instructions here. Keep in mind that the integration is an early research implementation and it is not yet production-ready!

Modularism, not maximalism.

· 6 min read

The original version of this blog post can be found on the Celestia blog.

Rollkit blog cover

Today, we’re pleased to introduce Rollkit, previously known as Rollmint. Rollkit is a modular rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

Rollkit provides a modular node for running rollups on top of a data availability layer. It exposes an ABCI-compatible client interface that can be used as a replacement for Tendermint for any ABCI-compatible blockchain app, including Cosmos chains.

In development since 2021, Rollkit is now emerging as neutral and independent from the Celestia blockchain. Rollkit will serve as a community-led public good for the modular ecosystem going forward, with its own docs site at rollkit.dev.

Tl;dr:

  • You can now build with Rollkit on Celestia’s Mocha testnet. Check out the docs
  • You can customize rollups and plug-in arbitrary data availability and execution layers by leveraging Rollkit’s modular framework
  • Join our Rollkit developer calls that begin in April to help guide its development

Deploying a new chain is hard

Deploying your decentralized application as a smart contract on a shared blockchain means it will share computational resources and is restricted to that blockchain's execution environment. This limits your application's scalability and flexibility.

For that reason, many developers have turned to launching their own layer 1 chains using tools like Tendermint and the Cosmos SDK. However, deploying a new layer 1 chain presents its own set of complex challenges and trade-offs.

In order to deploy a new layer 1 chain, a developer must gather a set of validators to secure the chain, issue a token to compensate these validators, and continuously maintain the network infrastructure. This represents a huge cost in social coordination, time, capital and expertise. This cost prevents many developers from launching their own chains and innovation from progressing as quickly as it could.

Freedom to deploy

Rollups are the answer to this problem. Rollups provide similar advantages as a layer 1 blockchain but reduce the overhead of deploying and maintaining your own chain.

Rollkit comparison table

Rollups provide similar benefits to blockchain developers that cloud infrastructure provides for traditional web developers. Deploying a new layer 1 blockchain is like maintaining a physical server, slow and expensive. Rollups remove the need for blockchain developers to launch and maintain their own layer 1s to deploy their own chain.

With Rollkit, developers no longer have to worry about the complex challenges of deploying a new blockchain. Rollkit will do for rollup chains what Tendermint did for layer 1 chains. The way it works is that rollups leverage an underlying layer for consensus, so that developers don’t need to build their own consensus networks. Rollkit rollups inherit security from the data availability layer, eliminating the need for a full set of validators and reducing the technical barrier for developers.

Vision for Rollkit

In the spirit of modularity, Rollkit’s long-term vision is to give developers a variety of options to choose from so that they can easily plug-in, switch or replace features in Rollkit.

In a rapidly evolving industry like blockchain, time to market and the ability to rapidly experiment and innovate are critical. Rollkit’s customizable stack will enable developers to bring their products to market faster and with more flexibility.

Rollkit lego image

Execution environments

Rollkit will allow you to easily swap in different execution environments. Not fond of the Cosmos SDK? Try Rust with CosmWasm. Still like Solidity? Plug in the EVM. None of the options suit your needs? Modify or add your own execution environment without needing to rebuild your entire chain from scratch.

Sequencers

Rollkit will support multiple sequencing modes to suit your specific use case. A single sequencer might be all you need. If your application requires stronger liveness, you can opt for multiple sequencers using your own set or leverage a set of shared sequencers.

Proof schemes

Rollkit will support a multitude of proof schemes to ensure the execution of your rollup. Run your application in zk mode, optimistic mode with fraud proofs, or pessimistic mode without any proofs.

Rollup types

Rollkit will allow you to build a diverse range of rollups, including sovereign rollups, settlement rollups and settled rollups.

Rollkit is in an early stage of development and many features remain to be built to reach this vision. In its current state, Rollkit rollups are sovereign rollups with single sequencers, with support for a pessimistic mode and a work-in-progress optimistic mode. Integration tutorials are ready and available with Cosmos SDK, Ethermint, and CosmWasm.

We invite the community to collaborate with us to build new features. Each new team that joins the growing Rollkit community brings more firepower to ship new features that we all benefit from. This is the power of modularity in action.

Rollkit is neutral

Celestia Labs originally started developing Rollkit in 2021, when the modular ecosystem was nascent and general-purpose rollup software did not exist. We started building Rollkit out of necessity, because having general-purpose software for rollup chains was critical to the Celestia mission of making deploying a new chain as easy as deploying a smart contract.

Since 2021 several projects have also started building general-purpose execution layer rollup software for various use cases. This includes Eclipse (Solana VM rollups), Dymension (settled Cosmos rollups), Sovereign Labs (sovereign ZK rollups), and Optimism (EVM rollups).

To ensure Celestia remains a decentralized and credibly neutral data availability layer that treats all rollup software as first class citizens, we decided to spin out Rollkit from Celestia Labs into its own project with its own GitHub org and docs site.

This also means that Rollkit aims to be neutral to the underlying data availability layer. Rollkit is designed to allow developers to integrate other data availability layers besides Celestia via the data availability interface.

The Celestia Labs Execution Environments team is currently contributing to the initial and necessary components of Rollkit, and is calling for all developers to contribute to it.

Spinning out Rollkit will enable both Celestia and Rollkit to serve the entire modular ecosystem as public goods that are neutral and independent from each other, and not favor each other in the modular stack.

We believe that to create a positive-sum crypto ecosystem where modularism thrives over maximalism, it’s important that developers have access to neutral rollup frameworks that are treated as public goods. In order for crypto to move into mainstream adoption, the industry needs to work together to create foundational developer tooling that will help crypto to level up.

Next steps

Moving towards a community-led project means increased visibility, transparency and inclusivity. That’s why the Rollkit team will soon release a roadmap blog post to detail ongoing work and its purpose. The team will also hold regular public calls with community members to showcase recent developments, discuss the roadmap and gather feedback from developers building with Rollkit. Keep an eye out for a new announcement from Rollkit.

Learn more about how Rollkit works on the new Rollkit website (you're already on it!). And don’t forget to check out the Rollkit repo too.

Let’s build modular together.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/category/advanced/index.html b/pr-preview/pr-192/docs/category/advanced/index.html deleted file mode 100644 index d5770598e..000000000 --- a/pr-preview/pr-192/docs/category/advanced/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Advanced | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/category/beginner/index.html b/pr-preview/pr-192/docs/category/beginner/index.html deleted file mode 100644 index f67c1e076..000000000 --- a/pr-preview/pr-192/docs/category/beginner/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Beginner | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/category/intermediate/index.html b/pr-preview/pr-192/docs/category/intermediate/index.html deleted file mode 100644 index 40f8f8886..000000000 --- a/pr-preview/pr-192/docs/category/intermediate/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Intermediate | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/category/tutorials/index.html b/pr-preview/pr-192/docs/category/tutorials/index.html deleted file mode 100644 index 4a12c5657..000000000 --- a/pr-preview/pr-192/docs/category/tutorials/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Tutorials | Rollkit - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/intro/index.html b/pr-preview/pr-192/docs/intro/index.html deleted file mode 100644 index 5305a27c0..000000000 --- a/pr-preview/pr-192/docs/intro/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - -Introduction to Rollkit | Rollkit - - - - - - - - - -
-

Introduction to Rollkit

Welcome to Rollkit docs. We're happy you made it here!

Our mission is to empower developers to quickly innovate and create entire new classes of rollups with minimal tradeoffs.

We're setting the bar high for developers' flexibility and ability to customize rollups however they see fit.

tip

In order to use Rollkit, it's important to have some -familiarity with Cosmos SDK. You can get up to speed -on Cosmos SDK by visiting their official documentation page.

If you're familiar with Rollkit, you may want to skip to the tutorials section.

What is Rollkit?

Rollkit is a rollup framework that gives developers the freedom to deploy rollups throughout the modular stack, opening new possibilities for rapid experimentation and innovation.

The Rollkit framework features a modular node that can run rollups and exposes an ABCI-compatible client interface, which can be used as a substitute for Tendermint in any ABCI-compatible blockchain application. -By default, the node utilizes Celestia as the data availability (DA) layer, however other data availability layers can be integrated.

Rollkit can currently be used to deploy sovereign rollups or sovereign settlement layers. In the future, we intend to support settled (not sovereign) rollups that settle to another settlement layer.

Rollkit is built as an open-source framework, so that developers can easily modify it to suit their applications.

Our goal is to empower developers to quickly innovate and create new classes of rollups with minimal trade-offs, and to make deploying a new chain as easy as deploying a smart contract.

What problems is Rollkit solving?

1. Scalability and customizability

Deploying your decentralized application as a smart contract on a shared blockchain has many limitations. Your smart contract has to share computational resources with every other application, so scalability is limited.

Plus, you're restricted to the execution environment that the shared blockchain uses, so developer flexibility is limited.

2. Security and time to market

Deploying a new chain might sound like the perfect solution for the problems listed above. While it's somewhat true, deploying a new layer 1 chain presents a complex set of challenges and trade-offs for developers looking to build blockchain products.

Deploying a new layer 1 requires significant resources, including time, capital, and expertise, which can be a barrier to entry for some developers.

In order to secure the network, developers must bootstrap a sufficiently secure set of validators, incurring the overhead of managing a full consensus network. This requires paying validators with inflationary tokens, putting the business sustainability of the network at risk. A strong community and network effect are also critical for success, but can be challenging to achieve as the network must gain widespread adoption to be secure and valuable.

In a potential future with millions of chains, it's unlikely all of those chains will be able to sustainably attract a sufficiently secure and decentralized validator set.

Why Rollkit?

Rollkit solves the challenges encountered during the deployment of a smart contract or a new layer 1, by minimizing these tradeoffs through the implementation of rollup chains (rollups).

With Rollkit, developers can benefit from:

  • Shared security: -Rollups inherit security from a data availability layer, by posting blocks to it. Rollups reduce the trust assumptions placed on rollup sequencers by allowing full nodes to download and verify the transactions in the blocks posted by the sequencer. For optimistic or zk rollups, in case of fraudulent blocks, full nodes can generate fraud or zk proofs, which they can share with the rest of the network, including light nodes. Our roadmap includes the ability for light clients to receive and verify proofs, so that everyday users can enjoy high security guarantees.

  • Scalability: -Rollkit rollups are deployed on specialized data availability layers like Celestia, which directly leverages the scalability of the DA layer. Additionally, rollup transactions are executed off-chain rather than the data availability layer. This means rollups have their own dedicated computational resources, rather than sharing computational resources with other applications.

  • Customizability: -Rollkit is built as an open source modular framework, to make it easier for developers to reuse existing components and customize their rollups. The data availability layers and execution environments used by rollups are customizable, as well as other components in the Rollkit stack.

  • Faster time to market: -Rollkit eliminates the need to bootstrap a validator set, manage a consensus network, incur high economic costs, and face other trade-offs that come with deploying a new layer 1. Rollkit's goal is to make deploying a rollup as easy as it is to deploy a smart contract, cutting the time it takes to bring blockchain products to market from months or even years to just minutes.

  • Sovereignty: Rollkit also enables developers to deploy sovereign rollups for cases where communities require sovereignty.

How can you use Rollkit?

As briefly mentioned above, Rollkit could be used in many different ways. From sovereign rollups, to settlement layers, and in the future even to L3s.

Rollup with any execution environment

Rollkit gives developers the flexibility to use pre-existing ABCI-compatible state machines or create a custom state machine tailored to their rollup needs. Rollkit does not restrict the use of any specific virtual machine, allowing developers to experiment and bring innovative applications to life.

Sovereign rollup with Cosmos SDK

Similarly to how developers utilize the Cosmos SDK to build a sovereign layer 1 chain, the Cosmos SDK could be utilized to create a Rollkit-compatible rollup chain. -Cosmos-SDK has great documentation and tooling that developers can leverage to learn.

Another possibility is taking an existing layer 1 built with the Cosmos SDK and deploying it as a Rollkit rollup. This can provide a great opportunity for experimentation and growth.

Build a settlement layer

Settlement layers are ideal for developers who want to avoid deploying sovereign rollups. They provide a platform for rollups to verify proofs and resolve disputes. -Additionally, they act as a hub for rollups to facilitate trust-minimized token transfers and liquidity sharing between rollups that share the same settlement layer. -Think of settlement layers as a special type of execution layer.

When can you use Rollkit?

As of today, Rollkit is still in the MVP stages. The framework currently provides a centralized sequencer, an execution interface (ABCI or Cosmos SDK), and a connection to a data availability layer (Celestia).

We're currently working on implementing many new and exciting features such as light nodes and state fraud proofs.

Head down to the next section (Rollkit Stack) to learn more about what's coming for Rollkit. If you're ready to start building, you can skip to the Tutorials section.

Spoiler alert, whichever you choose, it's going to be a great rabbit hole!

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/rollkit-stack/index.html b/pr-preview/pr-192/docs/rollkit-stack/index.html deleted file mode 100644 index 35a7003cb..000000000 --- a/pr-preview/pr-192/docs/rollkit-stack/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - -The Rollkit stack | Rollkit - - - - - - - - - -
-

The Rollkit stack

This page will cover the main components of Rollkit.

Rollup sequencer nodes collect transactions from users, aggregate them into blocks, and post the blocks onto a data availability (DA) layer (such as Celestia) to be ordered and finalized. Full nodes execute and verify rollup blocks, and in the case of an optimistic rollup, propagate fraud proofs when needed. Light clients will receive headers, verify proofs (fraud, zk, etc), and authenticate trust-minimized queries about the state.

Tip

If you're familiar with Rollkit's stack, you may want to skip to the tutorials section.

Application structure

Rollup architecture with Rollkit and ABCI.

ABCI interface

Rollkit is a fully functional Application BlockChain Interface (ABCI) client software. It can be used as a Tendermint replacement for any ABCI application. -Thanks to this compatibility, you can use tools like abci-cli to test and debug your rollup.

Cosmos SDK

Would you like to change your Cosmos SDK application to a Rollkit rollup? -No problem! You need to replace the Cosmos SDK Go dependency with a -Rollkit-enabled version, which can be found -at the rollkit/cosmos-sdk repository.

Note the rollkit/cosmos-sdk repository follows the release branches of -upstream Cosmos SDK, but with the bonus of using Rollkit instead of Tendermint -as the ABCI client.

And don't forget to replace another dependency, tendermint, with -rollkit/tendermint, which has an enhanced ABCI interface that includes -the methods needed for state fraud proofs.

Data availability

Data availability (DA) can be accessed using generic interfaces. This design allows for seamless integration with any DA layer. New implementations can be plugged in programmatically, without a need to fork Rollkit.

The DataAvailabilityLayerClient interface includes essential lifecycle methods (Init, Start, Stop) as well as data availability methods (SubmitBlock, CheckBlockAvailability).

The BlockRetriever interface serves to enable syncing of full nodes from the data availability layer. -It's important to keep in mind that there is no direct correlation between the DA layer block height and the rollup height. Each DA layer block may contain an arbitrary number of rollup blocks.

Celestia

Celestia is an example of a data availability integration implemented for Rollkit. -It's using the Celestia Node Gateway API -via the celestiaorg/go-cnc package. -To deploy a Rollkit rollup on Celestia you also have to run a Celestia light node.

Node components

Mempool

The mempool is inspired by the Tendermint mempool. By default, transactions are handled in a First Come, First Served (FCFS) manner. Ordering of transactions can be implemented on the application level; currently this is possible by returning a priority on CheckTx, and once we support ABCI++ it is also possible via PrepareProposal and the application mempool.

Block manager

The block manager contains Go routines AggregationLoop, RetrieveLoop, and SyncLoop that communicate through Go channels. These Go routines are ran when a Rollkit node starts up (OnStart). Only the sequencer nodes run AggregationLoop which controls the frequency of block production for a rollup with a timer as per the BlockTime in BlockManager.

All nodes run SyncLoop which looks for the following operations:

  • Receive block headers: block headers are received through a channel HeaderInCh and Rollkit nodes attempt to verify the block with the corresponding block data.
  • Receive block data: block bodies are received through a channel blockInCh and Rollkit nodes attempt to verify the block.
  • Receive state fraud proofs: state fraud proofs are received through a channel FraudProofInCh and Rollkit nodes attempt to verify them. Note that we plan to make this configurable for full nodes since full nodes also produce state fraud proofs on their own.
  • Signal RetrieveLoop with timer as per the DABlockTime in BlockManager.

All nodes also run RetrieveLoop which is responsible for interacting with the data availability layer. It checks the last updated DAHeight to retrieve a block with timer DABlockTime signaled by SyncLoop. Note that the start height of the DA layer for the rollup, DAStartHeight, is configurable in BlockManager.

RPC

Rollkit's RPC fully implements the Tendermint RPC interfaces and APIs for querying:

  • Information about the rollup node: information such as node's health, status, and network info.
  • The rollup blockchain: getting information about the rollup blockchain such as blocks and block headers.
  • The rollup transactions: getting transaction information and broadcasting raw transactions, with search capabilities.
  • ABCI: rollup application information.

The following RPC protocols are currently supported:

  • URI over HTTP
  • JSON-RPC over HTTP
  • JSON-RPC over WebSockets

P2P layer

Rollkit's P2P layer enables -direct communication between rollup nodes. -It's used to gossip transactions, headers of newly created blocks, and state fraud proofs. -The P2P layer is implemented using libp2p.

Rollkit uses DHT-based active peer discovery. -Starting a node connects to pre-configured bootstrap peers, and advertises its namespace ID in the DHT. -This solution is flexible, because multiple rollup networks may reuse the same DHT/bootstrap nodes, -but specific rollup network might decide to use dedicated nodes as well.

Rollkit node types

Rollkit nodes are implemented in the node package.

Full node

Full nodes verify all blocks, and produce fraud proofs for optimistic rollups. Since they fully verify all rollup blocks, they don't rely on fraud or validity proofs for security.

Light node (work in progress)

Light nodes are light-weight rollup nodes that authenticate block headers, and can be secured by fraud proofs or validity proofs. They're recommended for average users on low-resource devices. Users running light nodes can make trust-minimized queries about the rollup's state. Currently, Rollkit light nodes are still under development.

Sequencer node

Rollups can utilize sequencer nodes. Sequencers are block producers for rollups, responsible for aggregating transactions into blocks, and typically executing transactions to produce a state root, used by the rollup's light clients.

Rollkit plans to support multiple different pluggable sequencer schemes:

Deploy in one-clickFaster soft-confirmations than L1Control over rollup's transaction orderingAtomic composability with other rollupsCensorship resistanceImplementation Status
Centralized sequencerRequires spinning up a sequencerYes ✅Yes ✅No ❌Eventual ⏳*✅ Implemented!
Decentralized sequencerRequires spinning up a sequencer setYes ✅Yes ✅No ❌Real-time ⚡️Planned
Shared decentralized sequencerYes ✅Yes ✅No ❌Yes ✅Real-time ⚡️Planned
Pure fork-choice ruleYes ✅No ❌Maybe 🟡Maybe 🟡Eventual ⏳Planned

"Pure fork-choice rule" refers to any rollup without privileged sequencers, e.g. nodes defer to the data availability layer for ordering and apply a "first-come-first-serve" fork-choice rule.

* implementation of this property is in progress.

State validity modes

Pessimistic (full nodes only)

A pessimistic rollup is a rollup that only supports full nodes that replay all the transactions in the rollup in order to check its validity. Rollkit supports pessimistic rollups by default.

Pessimistic rollups are similar to how Tether uses Bitcoin as a data availability layer via OmniLayer.

Optimistic (fraud proofs) (work in progress)

Rollkit's current design consists of a single sequencer that posts blocks to the DA layer, and multiple (optional) full nodes. Sequencers gossip block headers to full nodes and full nodes fetch posted blocks from the DA layer. Full nodes then execute transactions in these blocks to update their state, and gossip block headers over the P2P network to Rollkit light nodes.

Once state fraud proofs are enabled, when a block contains a fraudulent state transition, Rollkit full nodes can detect it by comparing intermediate state roots (ISRs) between transactions, and generate a state fraud proof that can be gossiped over the P2P network to Rollkit light nodes. These Rollkit light nodes can then use this state fraud proof to verify whether a fraudulent state transition occurred or not by themselves.

Overall, state fraud proofs will enable trust-minimization between full nodes and light nodes as long as there is at least one honest full node in the system that will generate state fraud proofs.

Note that Rollkit state fraud proofs are still a work in progress and will require new methods on top of ABCI, specifically, GenerateFraudProof, VerifyFraudProof, and GetAppHash.

You can find current detailed design and the remaining work needed to push state fraud proofs towards completion in this Architecture Decision Record (ADR).

Validity (ZK proofs)

Validity (ZK) rollups are planned, but not currently supported by Rollkit.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/transaction-flow/index.html b/pr-preview/pr-192/docs/transaction-flow/index.html deleted file mode 100644 index 161309ff5..000000000 --- a/pr-preview/pr-192/docs/transaction-flow/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - -Transaction flow | Rollkit - - - - - - - - - -
-

Transaction flow

Rollup users use a light node to communicate with the rollup P2P network for two primary reasons:

  • submiting transactions
  • gossipping headers and fraud proofs
note

Light nodes are still a work in progress.

Here's what the typical transaction flow looks like:

tx-flow

To transact, users submit a transaction to their light node, which gossips the transaction to a full node. Before adding the transaction to their mempool, the full node checks its validity. Valid transactions are included in the mempool, while invalid ones are refused, and the user's transaction will not be processed.

If the transaction is valid and has been included in the mempool, the sequencer can add it to a rollup block, which is then submitted to the data availability (DA) layer. This results in a successful transaction flow for the user, and the state of the rollup is updated accordingly.

After the block is submitted to the DA layer, the full nodes download and validate the block. -However, there is a possibility that the sequencer may maliciously submit a block to the DA layer with invalid transactions or state. In such cases, the full nodes of the rollup chain will consider the block invalid. In the case of an optimistic rollup, if they find the block invalid, they generate fraud proofs and gossip them in the P2P network among other full and light nodes.

As a result, the rollup chain will halt, and the network will decide to fork the chain through social consensus. In the future, when a decentralized sequencer scheme is in place, additional options will be available, such as slashing the sequencer or selecting another full node as the sequencer. However, in any case, a new block must be created and submitted to the DA layer. You can read more about sequencer nodes here.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/bitcoin/index.html b/pr-preview/pr-192/docs/tutorials/bitcoin/index.html deleted file mode 100644 index 449e319a0..000000000 --- a/pr-preview/pr-192/docs/tutorials/bitcoin/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - -₿ Bitcoin rollup tutorial | Rollkit - - - - - - - - - -
-

₿ Bitcoin rollup tutorial

☀️Introduction

In this tutorial, we will explore how to use Rollkit to create sovereign rollups on Bitcoin. First, we will install Bitcoin Core to run a local testnet. Then, we will install and set up a Rollkit node to work with Bitcoin as a data availability layer. Lastly, we'll look at how to create a custom EVM execution environment and how to deploy a sovereign rollup on Bitcoin using Rollkit.

By the end of this tutorial, you will have a good understanding of how Rollkit works and how to create sovereign rollups on Bitcoin using Rollkit. You will also have the knowledge and skills needed to customize Rollkit with different execution environments and data availability layers, opening up new possibilities for creating scalable and efficient blockchain applications.

Read more in our blog post.

rollkit-bitcoin

📖 The stack

Sovereign rollups on Bitcoin are made possible through a module that allows Rollkit rollups to use Bitcoin for data availability. This integration opens up possibilities for developers to create rollups with arbitrary execution environments that inherit Bitcoin’s data availability guarantees and security guarantees.

The Taproot upgrade and Ordinals usage of Bitcoin for publishing arbitrary data made it possible to integrate Bitcoin as a data availability layer into Rollkit. The modular design of Rollkit allows for easy integration of new data availability layers, making it possible to deploy sovereign rollups on Bitcoin.

The goal of Rollkit is to make it easy to build and customize rollups, enabling developers to build sovereign rollups on Bitcoin or customize Rollkit with different execution environments and data availability layers.

💻 Prerequisites

An Ubuntu machine with:

  • 8GB RAM
  • 160 GB SSD
  • Ubuntu 22.10
  • 4 core AMD CPU

🛠️ Dependency setup

First, make sure to update and upgrade the OS:

sudo apt update && sudo apt upgrade -y

These are essential packages that are necessary to execute many tasks like downloading files, compiling, and monitoring the nodes:

sudo apt install curl tar wget clang pkg-config libssl-dev jq build-essential git make ncdu snapd npm -y

Now, we will install the remaining dependencies.

🏃 Golang

We will use golang to build and run our test networks. Install it for AMD with these commands:

ver="1.19.1"
cd $HOME
wget "https://golang.org/dl/go$ver.linux-amd64.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go$ver.linux-amd64.tar.gz"
rm "go$ver.linux-amd64.tar.gz"
echo "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile
source $HOME/.bash_profile
go version

⚒️ Foundry

Install Foundry:

curl -L https://foundry.paradigm.xyz/ | bash

Set the path:

source /root/.bashrc

Run this to finish the installation of Foundry:

foundryup

🪙 Install Bitcoin

Running the rollup requires a local regtest Bitcoin node. You can set this up by running the following commands.

Install Bitcoin Core:

sudo snap install bitcoin-core

Check version:

bitcoin-core.cli --version

🟢 Running a local Bitcoin network

Set up the config for regtest (local network):

bitcoin-core.daemon "-chain=regtest" "-rpcport=18332" "-rpcuser=rpcuser" "-rpcpassword=rpcpass" "-fallbackfee=0.000001" "-txindex=1"

👛 Create a wallet for the chain

Open up a new terminal and run the following to create a wallet:

bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass createwallet w1

Your output will look like:

{
"name": "w1",
"warning": ""
}

🎬 Start generating blocks

Now, generate a new address and mine 101 blocks:

export COINBASE=$(bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getnewaddress)
bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass generatetoaddress 101 $COINBASE

Next, we'll mine a block every second.

Add this script and remember where you placed it, I am putting it in my root directory:

# Script to generate a new block every second
# Put this script at the root of your unpacked folder
#!/bin/bash

echo "Generating a block every second. Press [CTRL+C] to stop.."

address=`bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getnewaddress`

while :
do
echo "Generate a new block `date '+%d/%m/%Y %H:%M:%S'`"
bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass generatetoaddress 1 $address
sleep 1
done

Run the following from where you placed your start.sh script. -Start generating blocks by running:

bash start.sh

🧊 Block height

Check the current block height:

bitcoin-core.cli -regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass getblockcount

Your output will look similar to below:

4980

Set a variable for the common flags being used:

export FLAGS="-regtest -rpcport=18332 -rpcuser=rpcuser -rpcpassword=rpcpass"

🧊 Block hash

Check the latest block hash:

bitcoin-core.cli $FLAGS getblockhash 4980

Your output will be the block hash of the height you first queried:

1d7e98aec3085b615c7c71659768fa42e774a87ab5981597e99794d240fb3db5

Set the block hash as a variable:

export HASH=1d7e98aec3085b615c7c71659768fa42e774a87ab5981597e99794d240fb3db5

🧊 Block header

Now to get the block header, run the following command (be sure to replace the hash with yours):

bitcoin-core.cli $FLAGS getblockheader $HASH

Now to finish the exercise, query the height from the block header and the hash:

bitcoin-core.cli $FLAGS getblockheader $HASH | jq '.height'

🎬 Restarting the local network

In the case that you are starting your regtest network again, you can use the following command to clear the old chain history:

rm -rf ${LOCATION OF .bitcoin folder}

🏃‍♀️ Running the Ethermint rollup

Clone Ethermint:

git clone https://github.com/celestiaorg/ethermint.git
cd ethermint
git checkout bitcoin-da
make install

Initialize the chain:

bash init.sh

Set variables for starting the chain:

export NAMESPACE_ID=$(openssl rand -hex 8)

Start the chain:

ethermintd start --rollkit.aggregator true --rollkit.da_layer bitcoin --rollkit.da_config='{"host":"127.0.0.1:18332","user":"rpcuser","pass":"rpcpass","http_post_mode":true,"disable_tls":true}' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height 1

Congratulations! Now that you have your Ethermint and Bitcoin rollup running, you're ready to deploy some smart contracts to the EVM!

⚡️ Initialize development environment

First, be sure you have -installed Foundry -on your local development environment.

Next, create a new project and change into the directory:

forge init bitcoin-ethermint-app
cd bitcoin-ethermint-app

Foundry has created an example smart contract located at src/Counter.sol.

tip

We will run the commands for the Foundry portion of this -tutorial in the ~/bitcoin-ethermint-app/ directory.

📒 Updating the contract and tests

Let's update the contracts to include a basic counter example. Open the -Counter.sol file in the src directory and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Counter {
int private count;

constructor(int _count) {
count = _count;
}

function incrementCounter() public {
count += 1;
}
function decrementCounter() public {
count -= 1;
}

function getCount() public view returns (int) {
return count;
}
}

Next, let's create a test for this contract.

Open test/Counter.T.Sol and update the code with the following:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import 'src/Counter.sol';

contract CounterTest is Test {
Counter counter;
function setUp() public {
counter = new Counter(10);
}

function testGetCount() public {
int value = counter.getCount();
assertEq(value, 10);
emit log_int(value);
}

function testIncrement() public {
counter.incrementCounter();
counter.incrementCounter();
int value = counter.getCount();
assertEq(value, 12);
emit log_int(value);
}

function testDecrement() public {
counter.decrementCounter();
int value = counter.getCount();
assertEq(value, 9);
emit log_int(value);
}
}

Foundry uses Dappsys Test to -provide basic logging and assertion functionality. It's included in the Forge -Standard Library.

Here, we are using assertEq to assert equality. You can view all of the assertion -functions available -here.

Next, we can test the contract using Forge with the following command:

forge test -vv

A successful test will have output similar to the following:

[] Compiling...
[] Installing solc version 0.8.17
[] Successfully installed solc 0.8.17
[] Compiling 18 files with 0.8.17
[] Solc 0.8.17 finished in 3.59s
Compiler run successful

Running 3 tests for test/Counter.t.sol:ContractTest
[PASS] testDecrement() (gas: 12350)
Logs:
9

[PASS] testGetCount() (gas: 8510)
Logs:
10

[PASS] testIncrement() (gas: 13285)
Logs:
12

Test result: ok. 3 passed; 0 failed; finished in 2.24ms

📜 Updating the deployment script

Now that we've tested the contract, let's try deploying it locally using -Solidity Scripting.

To do so, update the deloyment script at script/Counter.s.sol with the -following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "forge-std/Script.sol";

import {Counter} from "src/Counter.sol";

contract CounterScript is Script {
function setUp() public {}

function run() public {
vm.startBroadcast();
new Counter(10);
vm.stopBroadcast();
}
}

Now we can use this script to deploy our smart contract to either a live or -test network.

🏠 Deploying locally

Next start Anvil, the local testnet:

anvil --port 9545

Once started, Anvil will give you a local RPC endpoint as well as a handful -of Private Keys and Accounts that you can use.

Set ANVIL_KEY with one of the private keys generated by running:

export ANVIL_KEY=<anvil-private-key>

And set the RPC URL as an environment variable:

export RPC_URL=http://127.0.0.1:9545

We can now use the local RPC along with one of the private keys to deploy locally:

forge script script/Counter.s.sol:CounterScript --fork-url \
$RPC_URL --private-key $ANVIL_KEY --broadcast

Once the contract has been deployed locally, Anvil will log out the contract address.

Next, set the contract address as an environment variable:

export CONTRACT_ADDRESS=<contract-address>

We can then test sending transactions to it with cast send.

cast send $CONTRACT_ADDRESS "incrementCounter()" \
--private-key $ANVIL_KEY --rpc-url $RPC_URL

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url $RPC_URL

🧪 Deploying to the Ethermint sovereign rollup

Now that we've deployed and tested locally, we can deploy to our -Ethermint chain.

First, we will need to export the private key generated by -the ethermint init.sh script:

PRIVATE_KEY=$(ethermintd keys unsafe-export-eth-key mykey --keyring-backend test)

NOTE: Here, the key name from init.sh is mykey but you can modify -the init.sh to change the name of your key.

Now, we can start deploying the smart contract to our Ethermint chain.

To do so, run the following script:

forge script script/Counter.s.sol:CounterScript \
--rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY --broadcast

Set the contract address in the output as the CONTRACT_ADDRESS variable:

export CONTRACT_ADDRESS=<new-contract-address>

Once the contract has been deployed to the Ethermint rollup, we can -use cast send to test sending transactions to it:

cast send $CONTRACT_ADDRESS "incrementCounter()" \
--rpc-url http://127.0.0.1:8545 --private-key $PRIVATE_KEY

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url http://127.0.0.1:8545
- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/index.html b/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/index.html deleted file mode 100644 index b1d025088..000000000 --- a/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - -🗞️ Building a rollup and testnet deployment | Rollkit - - - - - - - - - -
-

🗞️ Building a rollup and testnet deployment

The following tutorials will help you get started building -Cosmos-SDK and EVM applications that connect to Celestia's data availability -(DA) layer via Rollkit to Celestia's -Mocha testnet -or Arabica devnet. We call those chains Sovereign Rollups.

You can get started with the following tutorials:

🔰 Beginner

🏃‍♂️ Intermediate

💎 Advanced

💻 Support

The tutorials will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -issue -or let us know in our Telegram. -Furthermore, while Rollkit allows you to build sovereign rollups -on Celestia, it currently does not support fraud proofs yet and is -therefore running in "pessimistic" mode, where nodes would need to -re-execute the transactions to check the validity of the chain -(i.e. a full node). Furthermore, Rollkit currently only supports -a single sequencer.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/cosmwasm/index.html b/pr-preview/pr-192/docs/tutorials/cosmwasm/index.html deleted file mode 100644 index ab6aa97bb..000000000 --- a/pr-preview/pr-192/docs/tutorials/cosmwasm/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - -🗞️ CosmWasm rollup | Rollkit - - - - - - - - - -
-

🗞️ CosmWasm rollup

CosmWasm is a smart contracting platform built for the Cosmos -ecosystem by making use of WebAssembly (Wasm) -to build smart contracts for Cosmos-SDK. In this tutorial, we will be -exploring how to integrate CosmWasm with Celestia's -data availability layer -using Rollkit.

note

This tutorial will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -Issue ticket -or let us know in our Telegram.

caution

The script for this tutorial is built for Celestia's -Blockspacerace testnet. -If you choose to use Mocha testnet or Arabica devnet, -you will need to modify the script manually.

You can learn more about CosmWasm here.

In this tutorial, we will going over the following:

  1. Setting up your dependencies for your CosmWasm smart contracts
  2. Setting up Rollkit on CosmWasm
  3. Instantiate a local network for your CosmWasm chain connected to Celestia
  4. Deploying a Rust smart contract to CosmWasm chain
  5. Interacting with the smart contract

The smart contract we will use for this tutorial is one provided by -the CosmWasm team for Nameservice purchasing.

You can check out the contract here.

How to write the Rust smart contract for Nameservice is outside the scope of -this tutorial. In the future we will add more tutorials for writing CosmWasm -smart contracts for Celestia.

💻 CosmWasm dependency installations

🛠️ Environment setup

For this tutorial, we will be using curl and jq as helpful -tools. You can follow the guide on installing them -here.

🏃 Golang dependency

The Golang version used for this tutorial is v1.18+

You can install Golang -by following our tutorial here.

🦀 Rust installation

🔨 Rustup

First, before installing Rust, you would need to install rustup.

On Mac and Linux systems, here are the commands for installing it:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
caution

You will see a note similar to below after installing Rust:

Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).

To configure your current shell, run:
source "$HOME/.cargo/env"

If you don't follow the guidance, you won't be able to continue with the -tutorial!

After installation, follow the commands here to setup Rust.

rustup default stable
cargo version

rustup target list --installed
rustup target add wasm32-unknown-unknown

Your output should look similar to below:

info: using existing install for 'stable-aarch64-apple-darwin'
info: default toolchain set to 'stable-aarch64-apple-darwin'

stable-aarch64-apple-darwin unchanged - rustc 1.65.0 (897e37553 2022-11-02)

cargo 1.65.0 (4bc8f24d3 2022-10-20)
aarch64-apple-darwin
info: downloading component 'rust-std' for 'wasm32-unknown-unknown'
info: installing component 'rust-std' for 'wasm32-unknown-unknown'

🐳 Docker installation

We will be using Docker later in this tutorial for compiling a smart contract -to use a small footprint. We recommend installing Docker on your machine.

Examples on how to install it on Linux are found here. -Find the right instructions specific for -your OS here.

💻 Wasmd installation

Here, we are going to pull down the wasmd repository and replace Tendermint -with Rollkit. Rollkit is a drop-in replacement for Tendermint that allows -Cosmos-SDK applications to connect to Celestia's data availability network.

git clone https://github.com/CosmWasm/wasmd.git
cd wasmd
git fetch --tags
git checkout v0.27.0
go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.45.10-rollkit-v0.7.3-no-fraud-proofs
go mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d
go mod tidy -compat=1.17
go mod download
make install

✨ Celestia node

You will need a light node running with test tokens on -Blockspace race testnet in order -to complete this tutorial. Please complete the tutorial -here, -or start up your node.

🌌 Setting up your environment for CosmWasm on Celestia

Now the wasmd binary is built, we need to setup a local network -that communicates between wasmd and Rollkit.

🗞️ Initializing CosmWasm rollup with a bash script

We have a handy init.sh found in this repo -here.

We can copy it over to our directory with the following commands:

# From inside the `wasmd` directory
wget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/cosmwasm/init.sh

This copies over our init.sh script to initialize our -CosmWasm rollup.

You can view the contents of the script to see how we -initialize the CosmWasm Rollup.

You can initialize the script with the following command:

bash init.sh

With that, we have kickstarted our wasmd network!

💠 Optional: see what's inside the script

You can skip this section, but it is important to know -how Rollkit is initializing the cosmwasm rollup.

Here are the contents of the script:

#!/bin/sh

VALIDATOR_NAME=validator1
CHAIN_ID=celeswasm
KEY_NAME=celeswasm-key
TOKEN_AMOUNT="10000000000000000000000000uwasm"
STAKING_AMOUNT=1000000000uwasm
CHAINFLAG="--chain-id ${CHAIN_ID}"
TXFLAG="--chain-id ${CHAIN_ID} --gas-prices 0uwasm --gas auto --gas-adjustment 1.3"

NAMESPACE_ID=$(openssl rand -hex 8)
echo $NAMESPACE_ID
DA_BLOCK_HEIGHT=$(curl https://rpc-mocha.pops.one/block | jq -r '.result.block.header.height')
echo $DA_BLOCK_HEIGHT

rm -rf "$HOME"/.wasmd
wasmd tendermint unsafe-reset-all
wasmd init $VALIDATOR_NAME --chain-id $CHAIN_ID

sed -i'' -e 's/^minimum-gas-prices *= .*/minimum-gas-prices = "0uwasm"/' "$HOME"/.wasmd/config/app.toml
sed -i'' -e '/\[api\]/,+3 s/enable *= .*/enable = true/' "$HOME"/.wasmd/config/app.toml
sed -i'' -e "s/^chain-id *= .*/chain-id = \"$CHAIN_ID\"/" "$HOME"/.wasmd/config/client.toml
sed -i'' -e '/\[rpc\]/,+3 s/laddr *= .*/laddr = "tcp:\/\/0.0.0.0:26657"/' "$HOME"/.wasmd/config/config.toml
sed -i'' -e 's/"time_iota_ms": "1000"/"time_iota_ms": "10"/' "$HOME"/.wasmd/config/genesis.json
sed -i'' -e 's/bond_denom": ".*"/bond_denom": "uwasm"/' "$HOME"/.wasmd/config/genesis.json
sed -i'' -e 's/mint_denom": ".*"/mint_denom": "uwasm"/' "$HOME"/.wasmd/config/genesis.json

wasmd keys add $KEY_NAME --keyring-backend test
wasmd add-genesis-account $KEY_NAME $TOKEN_AMOUNT --keyring-backend test
wasmd gentx $KEY_NAME $STAKING_AMOUNT --chain-id $CHAIN_ID --keyring-backend test
wasmd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config='{"base_url":"http://localhost:26659","timeout":60000000000,"fee":6000,"gas_limit":6000000}' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height $DA_BLOCK_HEIGHT

📒 Contract deployment on CosmWasm with Rollkit

🤖 Compile the smart contract

In a new terminal instance, we will run the following commands to pull down the -Nameservice smart contract and compile it:

git clone https://github.com/InterWasm/cw-contracts
cd cw-contracts
cd contracts/nameservice
cargo wasm

The compiled contract is outputted to: -target/wasm32-unknown-unknown/release/cw_nameservice.wasm.

🧪 Unit tests

If we want to run tests, we can do so with the following command in the -~/cw-contracts/contracts/nameservice directory:

cargo unit-test

🏎️ Optimized smart contract

Because we are deploying the compiled smart contract to wasmd, -we want it to be as small as possible.

The CosmWasm team provides a tool called rust-optimizer which we need -Docker for in order to compile.

AMD Machines

Run the following command in the ~/cw-contracts/contracts/nameservice -directory:

sudo docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.12.6

This will place the optimized Wasm bytecode at artifacts/cw_nameservice.wasm.

🚀 Contract deployment

Let's now deploy our smart contract!

AMD Machines

Run the following in the ~/cw-contracts/contracts/nameservice directory:

TX_HASH=$(wasmd tx wasm store artifacts/cw_nameservice.wasm --from celeswasm-key --keyring-backend test --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 --node http://127.0.0.1:26657 --output json -y | jq -r '.txhash') && echo $TX_HASH

This will get you the transaction hash for the smart contract deployment. Given -we are using Rollkit, there will be a delay on the transaction being included -due to Rollkit waiting on Celestia's data availability layer to confirm the block -has been included before submitting a new block.

important

If you run into errors with variables on the previous command, -or commands in the remainder of the tutorial, cross-reference -the variables in the command with the variables in the init.sh script.

🌟 Contract interaction on CosmWasm with Celestia

In the previous steps, we have stored out contract's tx hash in an -environment variable for later use.

Because of the longer time periods of submitting transactions via Rollkit -due to waiting on Celestia's data availability layer to confirm block inclusion, -we will need to query our tx hash directly to get information about it.

🔎 Contract querying

Let's start by querying our transaction hash for its code ID:

CODE_ID=$(wasmd query tx --type=hash $TX_HASH --chain-id celeswasm --node http://127.0.0.1:26657 --output json | jq -r '.logs[0].events[-1].attributes[0].value')
echo $CODE_ID

This will give us back the Code ID of the deployed contract.

In our case, since it's the first contract deployed on our local network, -the value is 1.

Now, we can take a look at the contracts instantiated by this Code ID:

wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --node http://127.0.0.1:26657 --output json

We get the following output:

{"contracts":[],"pagination":{"next_key":null,"total":"0"}}

📃 Contract instantiation

We start instantiating the contract by writing up the following INIT message -for nameservice contract. Here, we are specifying that purchase_price of a name -is 100uwasm and transfer_price is 999uwasm.

INIT='{"purchase_price":{"amount":"100","denom":"uwasm"},"transfer_price":{"amount":"999","denom":"uwasm"}}'
wasmd tx wasm instantiate $CODE_ID "$INIT" --from celeswasm-key --keyring-backend test --label "name service" --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 -y --no-admin --node http://127.0.0.1:26657

📄 Contract interaction

Now that we instantiated it, we can interact further with the contract:

wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --output json --node http://127.0.0.1:26657
CONTRACT=$(wasmd query wasm list-contract-by-code $CODE_ID --chain-id celeswasm --output json --node http://127.0.0.1:26657 | jq -r '.contracts[-1]')
echo $CONTRACT

wasmd query wasm contract --node http://127.0.0.1:26657 $CONTRACT --chain-id celeswasm
wasmd query bank balances --node http://127.0.0.1:26657 $CONTRACT --chain-id celeswasm

This allows us to see the contract address, contract details, and -bank balances.

Your output will look similar to below:

{"contracts":["wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d"],"pagination":{"next_key":null,"total":"0"}}
wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d
address: wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d
contract_info:
admin: ""
code_id: "1"
created: null
creator: wasm1y9ceqvnsnm9xtcdmhrjvv4rslgwfzmrzky2c5z
extension: null
ibc_port_id: ""
label: name service
balances: []
pagination:
next_key: null
total: "0"

Now, let's register a name to the contract for our wallet address:

REGISTER='{"register":{"name":"fred"}}'
wasmd tx wasm execute $CONTRACT "$REGISTER" --amount 100uwasm --from celeswasm-key --chain-id celeswasm --gas-prices 0uwasm --gas auto --gas-adjustment 1.3 --node http://127.0.0.1:26657 --keyring-backend test -y

Your output will look similar to below:

DEIP --keyring-backend test -y
gas estimate: 167533
code: 0
codespace: ""
data: ""
events: []
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: C147257485B72E7FFA5FDB943C94CE951A37817554339586FFD645AD2AA397C3

If you try to register the same name again, you'll see an expected error:

Error: rpc error: code = Unknown desc = rpc error: code = Unknown desc = failed to execute message; message index: 0: Name has been taken (name fred): execute wasm contract failed [CosmWasm/wasmd/x/wasm/keeper/keeper.go:364] With gas wanted: '0' and gas used: '123809' : unknown request

Next, query the owner of the name record:

NAME_QUERY='{"resolve_record": {"name": "fred"}}'
wasmd query wasm contract-state smart $CONTRACT "$NAME_QUERY" --chain-id celeswasm --node http://127.0.0.1:26657 --output json

You'll see the owner's address in a JSON response:

{"data":{"address":"wasm1y9ceqvnsnm9xtcdmhrjvv4rslgwfzmrzky2c5z"}}

With that, we have instantiated and interacted with the CosmWasm nameservice -smart contract using Celestia!

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/ethermint/index.html b/pr-preview/pr-192/docs/tutorials/ethermint/index.html deleted file mode 100644 index 0dafed645..000000000 --- a/pr-preview/pr-192/docs/tutorials/ethermint/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - -⧫ Ethermint (EVM) rollup | Rollkit - - - - - - - - - -
-

⧫ Ethermint (EVM) rollup

Ethermint is a Comsos-SDK library that integrates an EVM compiler -from Geth.

This would allow you to deploy Solidity or Vyper Ethereum smart contracts -in order to build Ethereum-based applications.

In this tutorial, we will be going over how to use Rollkit to deploy -an Ethereum-based sovereign rollup that uses Cosmos-SDK and Ethermint.

You can learn more about Ethermint here.

note

This tutorial will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -Issue ticket -or let us know in our Telegram.

caution

The script for this tutorial is built for Celestia's -Blockspacerace testnet. -If you choose to use Mocha testnet or Arabica devnet, -you will need to modify the script manually.

In this tutorial, we will go over the following:

💎 Ethermint dependencies

This section will guide you through installing the dependencies -you need for the deployment process of an Ethermint Sovereign Rollup -on Celestia.

💻 Hardware requirements

The following hardware minimum requirements are recommended for running -the full storage node:

  • Memory: 8 GB RAM
  • CPU: Quad-Core
  • Disk: 250 GB SSD Storage
  • Bandwidth: 1 Gbps for Download/100 Mbps for Upload

👾 Setting up your Ethermint node

The following tutorial is done on an Ubuntu Linux 20.04 (LTS) x64 instance machine.

🏃 Golang dependency

The Golang version used for this tutorial is v1.18+

If you are using a Linux distribution, you can install Golang -by following our tutorial here.

🗞️ Rollkit installation

👹 ethermintd installation

Here, we are going to pull down the ethermint from the -Celestia repository. -We will install Rollkit to this version of Ethermint. -Rollkit is a drop-in replacement for Tendermint that allows -Cosmos-SDK applications to connect to Celestia's data availability network.

git clone https://github.com/celestiaorg/ethermint.git
cd ethermint
make install

You can check if ethermintd is installed by running the following -command:

ethermintd

💻 Setting up your environment for Ethermint on Celestia

Now the ethermintd binary is built, we need to setup a local network -that communicates between ethermintd and Rollkit.

🏃‍♂️ Run a Celestia light node

All sovereign rollups need to submit their transaction data to -Celestia.

Here, we must first setup a Celestia Light Node with testnet tokens.

You can do this by following this tutorial here.

🌀 Instantiating the Ethermint rollup

With a Celestia Light Node running in one terminal session, -we can proceed to generate the Ethermint rollup.

In the ethermint directory, we have a helpful bash script that -allows you to instantiate a local Ethermint sovereign rollup on Celestia.

Run the following:

bash init.sh

This bash script does everything needed to initialize your Ethermint -rollup.

First, we need to setup some environment variables.

Networks

The commands below are for Blockspace Race. If you're using Mocha or Arabica, you'll need to -replace the RPC endpoint with one for Arabica or one for Mocha.

NAMESPACE_ID=$(openssl rand -hex 8)
DA_BLOCK_HEIGHT=$(curl https://rpc-blockspacerace.pops.one/block | jq -r '.result.block.header.height')

If you are running this on Celestia's -Mocha testnet -or Arabica devnet, you need to run your light node with an account -that has Mocha or Arabica tokens. Visit the faucet -here.

With this setup complete, we can now start our Ethermint Rollup:

ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config='{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6000}' --rollkit.namespace_id $NAMESPACE_ID --rollkit.da_start_height $DA_BLOCK_HEIGHT 

You should start seeing logs about the chain starting. -They will look similar to below:

1:27AM INF Unlocking keyring
1:27AM INF starting ABCI with Tendermint
1:27AM INF service start impl=EventBus module=events msg={}
1:27AM INF service start impl=PubSub module=pubsub msg={}
badger 2022/11/23 01:27:54 INFO: All 0 tables opened in 0s
badger 2022/11/23 01:27:54 INFO: Discard stats nextEmptySlot: 0
badger 2022/11/23 01:27:54 INFO: Set nextTxnTs to 0
1:27AM INF service start impl=IndexerService module=txindex msg={}
1:27AM INF WARNING: using default DA block time DABlockTime=30000 module=BlockManager
1:27AM INF initializing blockchain state from genesis.json
1:27AM INF created new capability module=ibc name=ports/transfer
1:27AM INF port binded module=x/ibc/port port=transfer
1:27AM INF claimed capability capability=1 module=transfer name=ports/transfer
1:27AM INF asserting crisis invariants inv=1/11 module=x/crisis name=gov/module-account
1:27AM INF asserting crisis invariants inv=2/11 module=x/crisis name=staking/module-accounts
1:27AM INF asserting crisis invariants inv=3/11 module=x/crisis name=staking/nonnegative-power
1:27AM INF asserting crisis invariants inv=4/11 module=x/crisis name=staking/positive-delegation
1:27AM INF asserting crisis invariants inv=5/11 module=x/crisis name=staking/delegator-shares
1:27AM INF asserting crisis invariants inv=6/11 module=x/crisis name=bank/nonnegative-outstanding
1:27AM INF asserting crisis invariants inv=7/11 module=x/crisis name=bank/total-supply
1:27AM INF asserting crisis invariants inv=8/11 module=x/crisis name=distribution/nonnegative-outstanding
1:27AM INF asserting crisis invariants inv=9/11 module=x/crisis name=distribution/can-withdraw
1:27AM INF asserting crisis invariants inv=10/11 module=x/crisis name=distribution/reference-count
1:27AM INF asserting crisis invariants inv=11/11 module=x/crisis name=distribution/module-account
1:27AM INF asserted all invariants duration=3.783918 height=0 module=x/crisis
1:27AM INF service start impl=RPC msg={}
1:27AM INF service start impl=Node msg={}
1:27AM INF serving HTTP listen address={"IP":"127.0.0.1","Port":26657,"Zone":""}
1:27AM INF starting P2P client
1:27AM INF listening on address=/ip4/143.244.145.92/tcp/26656/p2p/12D3KooWCrCqYheUBURCzzUqgxWFVFvFYPJ6nonTPN9uVQ4cXK5H module=p2p
1:27AM INF listening on address=/ip4/127.0.0.1/tcp/26656/p2p/12D3KooWCrCqYheUBURCzzUqgxWFVFvFYPJ6nonTPN9uVQ4cXK5H module=p2p
1:27AM INF no seed nodes - only listening for connections module=p2p
1:27AM INF starting Celestia Data Availability Layer Client baseURL=http://localhost:26659 module=da_client
1:27AM INF working in aggregator mode block time=30000
1:27AM INF Creating and publishing block height=1 module=BlockManager
1:27AM INF minted coins from module account amount=2059726034250856481aphoton from=mint module=x/bank
1:27AM INF submitting block to DA layer height=1 module=BlockManager
1:28AM INF Starting JSON-RPC server address=0.0.0.0:8545
1:28AM INF Starting JSON WebSocket server address=0.0.0.0:8546
1:28AM INF successfully submitted rollkit block to DA layer daHeight=25422 module=BlockManager rollkitHeight=1
1:28AM INF commit synced commit=436F6D6D697449447B5B323130203138352031373920362035322031333820373020313032203135322038302032323920313232203132342036332031382032313920313039203337203832203631203334203139302031323520393020323133203835203232382032323420323232203134203739203131305D3A317D
1:28AM INF indexed block height=1 module=txindex
1:28AM INF Creating and publishing block height=2 module=BlockManager
1:28AM INF minted coins from module account amount=2059726403014551280aphoton from=mint module=x/bank
1:28AM INF submitting block to DA layer height=2 module=BlockManager
1:28AM INF successfully submitted rollkit block to DA layer daHeight=25423 module=BlockManager rollkitHeight=2
1:28AM INF commit synced commit=436F6D6D697449447B5B3630203231332038372032313820383920313920323034203230322031363320383120323235203235352036352032323820313530203232392032333320323139203233322032343420313334203337203134342031303320313634203138382031393720323339203230342032303120323138203130325D3A327D
1:28AM INF indexed block height=2 module=txindex
1:28AM INF Creating and publishing block height=3 module=BlockManager
1:28AM INF minted coins from module account amount=2059726771778267119aphoton from=mint module=x/bank
1:28AM INF submitting block to DA layer height=3 module=BlockManager
1:29AM INF successfully submitted rollkit block to DA layer daHeight=25424 module=BlockManager rollkitHeight=3
1:29AM INF commit synced commit=436F6D6D697449447B5B313520323038203831203131203235332032322037322031393020333220323130203634203235332032303920313839203934203137203431203135203230302039362031383920323820313736203132332037352032392031393320313831203134312032303520323231203232325D3A337D
1:29AM INF indexed block height=3 module=txindex
1:29AM INF Creating and publishing block height=4 module=BlockManager
1:29AM INF minted coins from module account amount=2059727140542003996aphoton from=mint module=x/bank
1:29AM INF submitting block to DA layer height=4 module=BlockManager
1:29AM INF successfully submitted rollkit block to DA layer daHeight=25425 module=BlockManager rollkitHeight=4
1:29AM INF commit synced commit=436F6D6D697449447B5B313433203332203639203732203134342034352037302034302032392032303120393720313137203235312031393320313738203137362031353920323038203231372036312032362031353720353320393820323234203230352031373020313920313034203138372031323220385D3A347D
1:29AM INF indexed block height=4 module=txindex
1:29AM INF Creating and publishing block height=5 module=BlockManager

With that, we have kickstarted our ethermintd network!

📃 Deploy a Solidity smart contract on Ethermint sovereign rollup with Foundry

In this guide you'll learn how to deploy a Solidity smart contract to -the Ethermint chain you just instantiated on Celestia with -Foundry.

⚒️ About Foundry

Foundry is a portable, fast and modular toolkit for Ethereum application development.

Foundry is made up of three components:

  • Forge - Ethereum -testing framework (like Truffle, Hardhat and DappTools).
  • Cast - CLI for -interacting with EVM smart contracts, sending transactions, and getting chain data.
  • Anvil - Local -Ethereum node, similar to Ganache or Hardhat Network.

We'll use all three to create, test, and deploy our Solidity project.

To learn more about Foundry, check out the Foundry Book.

🎬 Getting started

⚡️ Initialize development environment

First, be sure to -install Foundry -on your local development environment.

Next, create a new project and change into the directory:

forge init celestia-ethermint-app
cd celestia-ethermint-app

Foundry has created an example smart contract located at src/Counter.sol.

📃 Updating the contract and tests

Let's update the contracts to include a basic counter example. Open the -Counter.sol file in the src directory and add the following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Counter {
int private count;

constructor(int _count) {
count = _count;
}

function incrementCounter() public {
count += 1;
}
function decrementCounter() public {
count -= 1;
}

function getCount() public view returns (int) {
return count;
}
}

Next, let's create a test for this contract.

Open test/Counter.T.Sol and update the code with the following:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import 'src/Counter.sol';

contract CounterTest is Test {
Counter counter;
function setUp() public {
counter = new Counter(10);
}

function testGetCount() public {
int value = counter.getCount();
assertEq(value, 10);
emit log_int(value);
}

function testIncrement() public {
counter.incrementCounter();
counter.incrementCounter();
int value = counter.getCount();
assertEq(value, 12);
emit log_int(value);
}

function testDecrement() public {
counter.decrementCounter();
int value = counter.getCount();
assertEq(value, 9);
emit log_int(value);
}
}

Foundry uses Dappsys Test to -provide basic logging and assertion functionality. It's included in the Forge -Standard Library.

Here, we are using assertEq to assert equality. You can view all of the assertion -functions available -here.

Next, we can test the contract using Forge with the following command:

forge test -vv

A successful test will have output similar to the following:

[] Compiling...
[] Installing solc version 0.8.17
[] Successfully installed solc 0.8.17
[] Compiling 18 files with 0.8.17
[] Solc 0.8.17 finished in 3.59s
Compiler run successful

Running 3 tests for test/Counter.t.sol:ContractTest
[PASS] testDecrement() (gas: 12350)
Logs:
9

[PASS] testGetCount() (gas: 8510)
Logs:
10

[PASS] testIncrement() (gas: 13285)
Logs:
12

Test result: ok. 3 passed; 0 failed; finished in 2.24ms

📒 Updating the deployment script

Now that we've tested the contract, let's try deploying it locally using -Solidity Scripting.

To do so, update the deloyment script at script/Counter.s.sol with the -following code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "forge-std/Script.sol";

import {Counter} from "src/Counter.sol";

contract CounterScript is Script {
function setUp() public {}

function run() public {
vm.startBroadcast();
new Counter(10);
vm.stopBroadcast();
}
}

Now we can use this script to deploy our smart contract to either a live or -test network.

🏠 Deploying locally

Next start Anvil, the local testnet:

anvil --port 9545

Once started, Anvil will give you a local RPC endpoint as well as a handful -of Private Keys and Accounts that you can use.

Set ANVIL_KEY with one of the private keys generated by running:

export ANVIL_KEY=<anvil-private-key>

And set the RPC URL as an environment variable:

export RPC_URL=http://127.0.0.1:9545

We can now use the local RPC along with one of the private keys to -deploy locally from the celestia-ethermint-app directory:

forge script script/Counter.s.sol:CounterScript --fork-url \
$RPC_URL --private-key $ANVIL_KEY --broadcast

Once the contract has been deployed locally, Anvil will log out the contract address.

Next, set the contract address as an environment variable:

export CONTRACT_ADDRESS=<contract-address>

We can then test sending transactions to it with cast send.

cast send $CONTRACT_ADDRESS "incrementCounter()" \
--private-key $ANVIL_KEY --rpc-url $RPC_URL

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url $RPC_URL

🟢 Deploying to the Ethermint sovereign rollup

Now that we've deployed and tested locally, we can deploy to our -Ethermint chain.

First, we will need to export the private key generated by -the ethermint init.sh script:

PRIVATE_KEY=$(ethermintd keys unsafe-export-eth-key mykey --keyring-backend test)

NOTE: Here, the key name from init.sh is mykey but you can modify -the init.sh to change the name of your key.

Now, we can start deploying the smart contract to our Ethermint chain.

To do so, run the following script from the -celestia-ethermint-app directory:

forge script script/Counter.s.sol:CounterScript \
--rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast

Set the contract address in the output as the CONTRACT_ADDRESS variable:

export CONTRACT_ADDRESS=<new-contract-address>

Once the contract has been deployed to the Ethermint rollup, we can -use cast send to test sending transactions to it:

cast send $CONTRACT_ADDRESS "incrementCounter()" \
--rpc-url http://localhost:8545 --private-key $PRIVATE_KEY

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url http://localhost:8545
- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/gm-world-frontend/index.html b/pr-preview/pr-192/docs/tutorials/gm-world-frontend/index.html deleted file mode 100644 index fdccfd065..000000000 --- a/pr-preview/pr-192/docs/tutorials/gm-world-frontend/index.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - -GM world frontend tutorial | Rollkit - - - - - - - - - -
-

GM world frontend tutorial

In this tutorial, we'll learn how to use Cosmology to -create a frontend for our GM world rollup.

Cosmology enables developers to build web3 apps in the Interchain Ecosystem. -With Cosmology, it's simple to begin building apps that communicate with -Cosmos SDK and CosmWasm chains.

We'll be using create-cosmos-app in this tutorial to scaffold -a frontend and add the chain information for our rollup.

In the end, you'll have something that looks like this -demo -(repo).

Getting started

In order to complete this tutorial you will need to have completed -the GM world tutorial. This requires a running rollup -on your local machine.

Setting up the frontend

Now that you have your rollup running, you are ready to scaffold -the frontend! In your terminal, first install create-cosmos-app:

npm install -g create-cosmos-app

Now scaffold an app:

create-cosmos-app

In this tutorial, we're using the following setting and your output -will look similar to this if everything is successful:

? [name] Enter your new app name gm-world
Cloning into 'gm-world'...
? [template] which template connect-multi-chain
yarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 42.23s.


| _ _
=== |.===. '\-//`
(o o) {}o o{} (o o)
ooO--(_)--Ooo-ooO--(_)--Ooo-ooO--(_)--Ooo-

✨ Have fun! Now you can start on your project ⚛️

Now, run this command:

cd ./gm-world && yarn dev

Follow the instructions at the end of the output to start your app:

cd ./gm-world && yarn dev

cca-3.png

Adding your GM portal chain to the config

First, we'll need to make some changes with the default config.

We need to add the array of chains that we would like to test -in the components/wallet.tsx file on underneath imports:

const allowedChains = [
'gmrollup',
'celestiatestnet',
'celestiatestnet2',
'celestiatestnet3',
];

In chainOptions change chainRecords this to show only the allowed chains -from your array:

hi
chainRecords
.filter((chainRecord) => allowedChains.includes(chainRecord.name))
.map((chainRecord) => {

In configs/defaults.ts change defaultChainName to:

export const defaultChainName = 'gmrollup';

Now you're ready to see only the chains you've selected, but first, we need -to set up the config for gmrollup!

In the config directory, create a new file called chain.ts. This will -be your config for your GM rollup.

In that file, put the following:

export const chain = {
"$schema": "../../chain.schema.json",
"chain_name": "gmrollup",
"chain_id": "gm",
"pretty_name": "my gm rollup",
"status": "live",
"network_type": "testnet",
"bech32_prefix": "gm",
"daemon_name": "gmd",
"node_home": "$HOME/.gm",
"key_algos": [
"secp256k1"
],
"slip44": 118,
"fees": {
"fee_tokens": [
{
"denom": "ustake",
"fixed_min_gas_price": 0
}
]
},
"apis": {
"rpc": [
{
"address": "http://localhost:26657",
"provider": "JCS"
}
],
"rest": [
{
"address": "http://localhost:1317",
"provider": "JCS"
}
]
},
"beta": true,
}

Create a new file in config called assetlist.ts and add the following:

export const assetlist = {
"$schema": "../../assetlist.schema.json",
"chain_name": "gmrollup",
"assets": [
{
"description": "",
"denom_units": [
{
"denom": "ustake",
"exponent": 0
},
{
"denom": "stake",
"exponent": 6
}
],
"base": "stake",
"name": "GM rollup",
"display": "stake",
"symbol": "STAKE",
"logo_URIs": {
"svg": "https://raw.githubusercontent.com/jcstein/gm-portal/b030ce3fe548d188fbacb6b932d7e51dc7afd65e/frontend/public/gm.svg"
}
}
]
}

Create a new file in config directory called defaults.ts:

import { assets } from 'chain-registry';
import { AssetList, Asset } from '@chain-registry/types';

export const defaultChainName = 'gmrollup';

export const getChainAssets = (chainName: string = defaultChainName) => {
return assets.find((chain) => chain.chain_name === chainName) as AssetList;
};

export const getCoin = (chainName: string = defaultChainName) => {
const chainAssets = getChainAssets(chainName);
return chainAssets.assets[0] as Asset;
};

In _app.tsx you can now import assetlist and chain with your -new GM config!

# other imports
import { chain } from "../config/chain"
import { assetlist } from "../config/assetlist"

# rest of code

Then, modify your ChainProvider:

<ChainProvider
chains={[...chains, chain]}
assetLists={[...assets, assetlist]}
wallets={[...keplrWallets, ...cosmostationWallets, ...leapWallets]}
walletConnectOptions={{
signClient: {
projectId: 'a8510432ebb71e6948cfd6cde54b70f7',
relayUrl: 'wss://relay.walletconnect.org',
metadata: {
name: 'Celestia + Cosmos SDK',
description: 'Celestia + Cosmos SDK',
url: 'https://docs.celestia.org/',
icons: [],
},
},
}}
endpointOptions={{
isLazy: true
}}
wrappedWithChakra={true}
signerOptions={signerOptions}
>

You may notice that we added:

endpointOptions={{isLazy: true}}

This will save our localhost RPC from being overridden.

Congratulations! You now have a frontend for your rollup. -What features do you want to add now?

You may notice that the icons for Celestia testnets are not loading, -this is due to an outdated version of the chain registry.

cca.png

To update -these, you can use your terminal:

cd $HOME && cd gm-world
yarn upgrade-interactive --latest

Select @chain-registry/types by using arrow keys and the spacebar -to select it. Do the same with @cosmos-kit/core, @cosmos-kit -cosmostation, @cosmos-kit/keplr, @cosmos-kit/leap, -@cosmos-kit/react, @chain-registry/cosmostation and -chain-registry.

Now use enter to upgrade the dependencies!

Head back to your frontend and take a look, you should see the -updated icons.

cca-2.png

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/gm-world/index.html b/pr-preview/pr-192/docs/tutorials/gm-world/index.html deleted file mode 100644 index e10df77e8..000000000 --- a/pr-preview/pr-192/docs/tutorials/gm-world/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - -GM world rollup | Rollkit - - - - - - - - - -
-

GM world rollup

☀️ Introduction

In this tutorial, we will build a sovereign gm-world rollup using Rollkit -and Celestia’s data availability and consensus layer to submit Rollkit blocks.

This tutorial will cover setting up Ignite CLI, -building a Cosmos-SDK application-specific rollup blockchain, -and posting data to Celestia. -First, we will test on a local DA network and then we will deploy to a live -testnet.

The Cosmos SDK is a framework for -building blockchain applications. The Cosmos Ecosystem uses -Inter-Blockchain Communication (IBC) -to allow blockchains to communicate with one another.

The development journey for your rollup will look something like this:

  1. Part one: Run your rollup and post DA to a local devnet, and make sure everything works as expected
  2. Part two: Deploy the rollup, posting to a DA testnet. Confirm again that everything is functioning properly
  3. Coming soon: Deploy your rollup to the DA layer's mainnet
note

This tutorial will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -Issue ticket -or let us know in our Telegram.

caution

The scripts for this tutorial are built for Celestia's -Blockspacerace testnet. -If you choose to use Mocha testnet or Arabica devnet, -you will need to modify the script manually.

🤔 What is GM?

GM means good morning. It's GM o'clock somewhere, so there's never a bad time -to say GM, Gm, or gm. You can think of "GM" as the new version of -"hello world".

Dependencies

tip

If you are only planning to complete Part one, -feel free to skip to the Part two.

Be sure to use the same testnet installation instructions through this -entire tutorial.

🏃 Install Golang on Linux

Celestia-App, -Celestia-Node, -and Cosmos-SDK are -written in the Golang programming language. You will need -Golang to build and run them.

You can install Golang here.

🔥 Install Ignite CLI on Linux

First, you will need to create /usr/local/bin if you have not already:

sudo mkdir -p -m 775 /usr/local/bin

Run this command in your terminal to install Ignite CLI:

curl https://get.ignite.com/cli@v0.26.1! | bash
tip

✋ On some machines, you may run into permissions errors like the one below. -You can resolve this error by following the guidance -here or below.

# Error
jcs @ ~ % curl https://get.ignite.com/cli@v0.26.1! | bash


% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3967 0 3967 0 0 16847 0 --:--:-- --:--:-- --:--:-- 17475
Installing ignite v0.26.1.....
######################################################################## 100.0%
mv: rename ./ignite to /usr/local/bin/ignite: Permission denied
============
Error: mv failed

The following command will resolve the permissions error:

sudo curl https://get.ignite.com/cli@v0.26.1! | sudo bash

A successful installation will return something similar the response below:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload Upload Total Spent Left Speed
100 3967 0 3967 0 0 15586 0 --:--:-- --:--:-- --:--:-- 15931
Installing ignite v0.26.1.....
######################################################################## 100.0%
Installed at /usr/local/bin/ignite

Verify you’ve installed Ignite CLI by running:

ignite version

The response that you receive should look something like this:

jcs @ ~ % ignite version
Ignite CLI version: v0.26.1
Ignite CLI build date: 2022-10-20T15:52:00Z
Ignite CLI source hash: cc393a9b59a8792b256432fafb472e5ac0738f7c
Cosmos SDK version: v0.46.3
Your OS: darwin
Your arch: arm64
Your Node.js version: v18.10.0
Your go version: go version go1.19.2 darwin/arm64
Your uname -a: Darwin Joshs-MacBook-Air.local 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:20:07 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T8110 arm64
Your cwd: /Users/joshstein
Is on Gitpod: false

Part one

This part of the tutorial will teach developers how to easily run a local data availability (DA) devnet on their own machine (or in the cloud). -Running a local devnet for DA to test your rollup is the recommended first step before deploying to a testnet. -This eliminates the need for testnet tokens and deploying to a testnet until you are ready.

Note

Part one of the tutorial has only been tested on an AMD machine running Ubuntu 22.10 x64.

Whether you're a developer simply testing things on your laptop or using a virtual machine in the cloud, -this process can be done on any machine of your choosing. We tested out the Devnet section (Part one) on a machine with the following specs:

  • Memory: 1 GB RAM
  • CPU: Single Core AMD
  • Disk: 25 GB SSD Storage
  • OS: Ubuntu 22.10 x64

💻 Prerequisites

  • Docker installed on your machine

🏠 Running local devnet with a Rollkit rollup

First, run the local-celestia-devnet by running the following command:

docker run --platform linux/amd64 -p 26650:26657 -p 26659:26659 ghcr.io/rollkit/local-celestia-devnet:v0.9.1
tip

Port 26657 on the Docker container in this example will be mapped to the local port 26650. This is to avoid clashing ports with -the Rollkit node, as we're running the devnet and node on one machine.

🔎 Query your balance

Open a new terminal instance. Check the balance on your account that you'll be using to post blocks to the -local network, this will make sure you can post rollup blocks to your Celestia Devnet for DA & consensus:

curl -X GET http://0.0.0.0:26659/balance

You will see something like this, denoting your balance in TIA x 10-6:

{"denom":"utia","amount":"999995000000000"}

If you want to be able to transpose your JSON results in a nicer format, you can install jq:

sudo apt install jq
tip

We'll need jq later, so install it!

Then run this to prettify the result:

curl -X GET http://0.0.0.0:26659/balance | jq

Here's what my response was when I wrote this:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload Upload Total Spent Left Speed
100 43 100 43 0 0 1730 0 --:--:-- --:--:-- --:--:-- 1791
{
"denom": "utia",
"amount": "999995000000000"
}

If you want to clean it up some more, you can use the -s option to run curl in silent mode and not print the progress metrics:

curl -s -X GET http://0.0.0.0:26659/balance | jq

Your result will now look like this, nice 🫡

{
"denom": "utia",
"amount": "999995000000000"
}

🟢 Start, stop, or remove your container

Find the Container ID that is running by using the command:

docker ps

Then stop the container:

docker stop CONTAINER_ID_or_NAME

You can obtain the container ID or name of a stopped container using the docker ps -a command, which will list all containers (running and stopped) and their details. For example:

docker ps -a

This will give you an output similar to this:

CONTAINER ID   IMAGE                                            COMMAND            CREATED         STATUS         PORTS                                                                                                                         NAMES
d9af68de54e4 ghcr.io/rollkit/local-celestia-devnet:v0.9.1 "/entrypoint.sh" 5 minutes ago Up 2 minutes 1317/tcp, 9090/tcp, 0.0.0.0:26657->26657/tcp, :::26657->26657/tcp, 26656/tcp, 0.0.0.0:26659->26659/tcp, :::26659->26659/tcp musing_matsumoto

In this example, you can restart the container using either its container ID (d9af68de54e4) or name (musing_matsumoto). To restart the container, run:

docker start d9af68de54e4

or

docker start musing_matsumoto

If you ever would like to remove the container, you can use the docker rm command followed by the container ID or name.

Here is an example:

docker rm CONTAINER_ID_or_NAME

🏗️ Building your sovereign rollup

Now that you have a Celestia devnet running, you are ready to install Golang. We will use Golang to build and run our Cosmos-SDK blockchain.

The Ignite CLI comes with scaffolding commands to make development of -blockchains quicker by creating everything that is needed to start a new -Cosmos SDK blockchain.

Install Golang (these commands are for amd64/linux):

cd $HOME
ver="1.19.1"
wget "https://golang.org/dl/go$ver.linux-amd64.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go$ver.linux-amd64.tar.gz"
rm "go$ver.linux-amd64.tar.gz"
echo "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile
source $HOME/.bash_profile
go version

Now, use the following command to install Ignite CLI:

curl https://get.ignite.com/cli@v0.26.1! | bash
tip

If you have issues with installation, the full guide can be found here or on docs.ignite.com. -The above command was tested on amd64/linux.

Check your version:

ignite version

Open a new tab or window in your terminal and run this command to -scaffold your rollup. Scaffold the chain:

cd $HOME
ignite scaffold chain gm --address-prefix gm
tip

The --address-prefix gm flag will change the address prefix from cosmos to gm. Read more on the Cosmos docs.

The response will look similar to below:

jcs @ ~ % ignite scaffold chain gm --address-prefix gm

⭐️ Successfully created a new blockchain 'gm'.
👉 Get started with the following commands:

% cd gm
% ignite chain serve

Documentation: https://docs.ignite.com

This command has created a Cosmos SDK blockchain in the gm directory. The -gm directory contains a fully functional blockchain. The following standard -Cosmos SDK modules have been -imported:

  • staking - for delegated Proof-of-Stake (PoS) consensus mechanism
  • bank - for fungible token transfers between accounts
  • gov - for on-chain governance
  • mint - for minting new units of staking token
  • nft - for creating, transferring, and updating NFTs
  • and more

Change to the gm directory:

cd gm

You can learn more about the gm directory’s file structure here. -Most of our work in this tutorial will happen in the x directory.

🗞️ Install Rollkit

To swap out Tendermint for Rollkit, run the following command -from inside the gm directory:

go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs
go mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d
go mod tidy
go mod download

▶️ Start your rollup

Download the init.sh script to start the chain:

# From inside the `gm` directory
wget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/gm/init-local.sh

Run the init-local.sh script:

bash init-local.sh

This will start your rollup, connected to the local Celestia devnet you have running.

Now let's explore a bit.

🔑 Keys

List your keys:

gmd keys list --keyring-backend test

You should see an output like the following

- address: gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7
name: gm-key-2
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AlXXb6Op8DdwCejeYkGWbF4G3pDLDO+rYiVWKPKuvYaz"}'
type: local
- address: gm13nf52x452c527nycahthqq4y9phcmvat9nejl2
name: gm-key
pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AwigPerY+eeC2WAabA6iW1AipAQora5Dwmo1SnMnjavt"}'
type: local

💸 Transactions

Now we can test sending a transaction from one of our keys to the other. We can do that with the following command:

gmd tx bank send [from_key_or_address] [to_address] [amount] [flags]

Set your keys as variables to make it easier to add the address:

export KEY1=gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7
export KEY2=gm13nf52x452c527nycahthqq4y9phcmvat9nejl2

So using our information from the keys command, we can construct the transaction command like so to send 42069stake from one address to another:

gmd tx bank send $KEY1 $KEY2 42069stake --keyring-backend test

You'll be prompted to accept the transaction:

auth_info:
fee:
amount: []
gas_limit: "200000"
granter: ""
payer: ""
signer_infos: []
tip: null
body:
extension_options: []
memo: ""
messages:
- '@type': /cosmos.bank.v1beta1.MsgSend
amount:
- amount: "42069"
denom: stake
from_address: gm1sa3xvrkvwhktjppxzaayst7s7z4ar06rk37jq7
to_address: gm13nf52x452c527nycahthqq4y9phcmvat9nejl2
non_critical_extension_options: []
timeout_height: "0"
signatures: []
confirm transaction before signing and broadcasting [y/N]:

Type y if you'd like to confirm and sign the transaction. Then, you'll see the confirmation:

code: 0
codespace: ""
data: ""
events: []
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: '[]'
timestamp: ""
tx: null
txhash: 677CAF6C80B85ACEF6F9EC7906FB3CB021322AAC78B015FA07D5112F2F824BFF

⚖️ Balances

Then, query your balance:

gmd query bank balances $KEY2

This is the key that received the balance, so it should have increased past the initial STAKING_AMOUNT:

balances:
- amount: "10000000000000000000042069"
denom: stake
pagination:
next_key: null
total: "0"

The other key, should have decreased in balance:

gmd query bank balances $KEY1

Response:

balances:
- amount: "9999999999999999999957931"
denom: stake
pagination:
next_key: null
total: "0"

Part two

🪶 Run a Celestia light node

Follow instructions to install and start your Celestia Data Availalbility -layer Light Node selecting the network that you had previously used. You can -find instructions to install and run the node here.

After you have Go and Ignite CLI installed, and your Celestia Light -Node running on your machine, you're ready to build, test, and launch your own -sovereign rollup.

💬 Say gm world

Now, we're going to get our blockchain to say gm world! - in order to do so -you need to make the following changes:

  • Modify a protocol buffer file
  • Create a keeper query function that returns data

Protocol buffer files contain proto RPC calls that define Cosmos SDK queries -and message handlers, and proto messages that define Cosmos SDK types. The RPC -calls are also responsible for exposing an HTTP API.

The Keeper is required for each Cosmos SDK module and is an abstraction for -modifying the state of the blockchain. Keeper functions allow us to query or -write to the state.

✋ Create your first query

Open a new terminal instance that is not the -same that you started the chain in.

In your new terminal, cd into the gm directory and run this command -to create the gm query:

ignite scaffold query gm --response text

Response:

modify proto/gm/gm/query.proto
modify x/gm/client/cli/query.go
create x/gm/client/cli/query_gm.go
create x/gm/keeper/query_gm.go

🎉 Created a query `gm`.

What just happened? query accepts the name of the query (gm), an optional -list of request parameters (empty in this tutorial), and an optional -comma-separated list of response field with a --response flag (text in this -tutorial).

Navigate to the gm/proto/gm/gm/query.proto file, you’ll see that Gm RPC has -been added to the Query service:

gm/proto/gm/gm/query.proto
service Query {
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/gm/gm/params";
}
rpc Gm(QueryGmRequest) returns (QueryGmResponse) {
option (google.api.http).get = "/gm/gm/gm";
}
}

The Gm RPC for the Query service:

  • is responsible for returning a text string
  • Accepts request parameters (QueryGmRequest)
  • Returns response of type QueryGmResponse
  • The option defines the endpoint that is used by gRPC to generate an HTTP API

📨 Query request and response types

In the same file, we will find:

  • QueryGmRequest is empty because it does not require parameters
  • QueryGmResponse contains text that is returned from the chain
gm/proto/gm/gm/query.proto
message QueryGmRequest {
}

message QueryGmResponse {
string text = 1;
}

👋 Gm keeper function

The gm/x/gm/keeper/query_gm.go file contains the Gm keeper function that -handles the query and returns data.

gm/x/gm/keeper/query_gm.go
func (k Keeper) Gm(goCtx context.Context, req *types.QueryGmRequest) (*types.QueryGmResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
ctx := sdk.UnwrapSDKContext(goCtx)
_ = ctx
return &types.QueryGmResponse{}, nil
}

The Gm function performs the following actions:

  • Makes a basic check on the request and throws an error if it’s nil
  • Stores context in a ctx variable that contains information about the -environment of the request
  • Returns a response of type QueryGmResponse

Currently, the response is empty and you'll need to update the keeper function.

Our query.proto file defines that the response accepts text. Use your text -editor to modify the keeper function in gm/x/gm/keeper/query_gm.go .

gm/x/gm/keeper/query_gm.go
func (k Keeper) Gm(goCtx context.Context, req *types.QueryGmRequest) (*types.QueryGmResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
ctx := sdk.UnwrapSDKContext(goCtx)
_ = ctx
return &types.QueryGmResponse{Text: "gm world!"}, nil
}

🟢 Start your sovereign rollup

caution

Before starting our rollup, we'll need to find and change -FlagIAVLFastNode to FlagDisableIAVLFastNode:

gm/cmd/gmd/cmd/root.go
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(server.FlagDisableIAVLFastNode))),

We have a handy init-testnet.sh found in this repo -here.

We can copy it over to our directory with the following commands:

# From inside the `gm` directory
wget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/gm/init-testnet.sh

This copies over our init-testnet.sh script to initialize our -gm rollup.

You can view the contents of the script to see how we -initialize the gm rollup.

Clear previous chain history

Before starting the rollup, we need to remove the old project folders:

cd $HOME
rm -r go/bin/gmd && rm -rf .gm
Start the new chain

Now, you can initialize the script with the following command:

bash init-testnet.sh

With that, we have kickstarted our second gmd network!

The query command has also scaffolded -x/gm/client/cli/query_gm.go that -implements a CLI equivalent of the gm query and mounted this command in -x/gm/client/cli/query.go.

In a separate window, run the following command:

gmd q gm gm

We will get the following JSON response:

text: gm world!

4.png

Congratulations 🎉 you've successfully built your first rollup and queried it!

If you're interested in looking at the demo repository -for this tutorial, you can at https://github.com/rollkit/gm.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/recipe-book/index.html b/pr-preview/pr-192/docs/tutorials/recipe-book/index.html deleted file mode 100644 index e7e035134..000000000 --- a/pr-preview/pr-192/docs/tutorials/recipe-book/index.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - -🥗 Recipe book rollup | Rollkit - - - - - - - - - -
-

🥗 Recipe book rollup

📖 Overview

In this tutorial, we are going to build a blockchain -for your favorite recipes. The goal of this tutorial -is to create a Rollkit rollup with a module that allows -you to write and read data to and from your application-specific -blockchain. The end user will be able to submit new -recipes and read them from the blockchain.

In the GM World tutorial, we defined a -new API endpoint and modified a keeper query function -to return static data. In this tutorial, we will be -modifying the state with transactions (Cosmos SDK messages) -that are routed to a module and its message handlers, which -are sent to the recipes blockchain.

note

This tutorial will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -Issue ticket -or let us know in our Telegram.

caution

The script for this tutorial is built for Celestia's -Blockspacerace testnet. -If you choose to use Mocha testnet or Arabica devnet, -you will need to modify the script manually.

💻 Prerequisites

🏗 Scaffolding your rollup

🔥 Use Ignite CLI to scaffold a recipes rollup

Run the following command to scaffold your recipes chain using Ignite CLI:

ignite scaffold chain recipes --address-prefix recipes

Your new recipes chain has been scaffolded and ---address-prefix recipes allows the address prefix -to be recipes instead of cosmos.

Change into the recipes directory:

cd recipes

💎 Installing Rollkit

To swap out Tendermint for Rollkit, run the following commands:

go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs
go mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d
go mod tidy
go mod download

💬 Message types

✨ Create message types

Create a message type and its handler with the message command:

ignite scaffold message createRecipe dish ingredients

Response:

modify proto/recipes/recipes/tx.proto
modify x/recipes/client/cli/tx.go
create x/recipes/client/cli/tx_create_recipe.go
create x/recipes/keeper/msg_server_create_recipe.go
modify x/recipes/module_simulation.go
create x/recipes/simulation/create_recipe.go
modify x/recipes/types/codec.go
create x/recipes/types/message_create_recipe.go
create x/recipes/types/message_create_recipe_test.go

🎉 Created a message `createRecipe`.

Head to your recipes/proto/recipes/recipes/tx.proto file -and you will see the MsgCreateRecipe has been created. -Add uint64 id = 1; to the MsgCreateRecipeResponse function:

recipes/proto/recipes/recipes/tx.proto
message MsgCreateRecipeResponse {
uint64 id = 1;
}

🤿 Diving deeper into the message code

Looking further into the message, we can see that -MsgCreateRecipe has 3 fields: creator, dish, and ingredients.

recipes/proto/recipes/recipes/tx.proto
message MsgCreateRecipe {
string creator = 1;
string dish = 2;
string ingredients = 3;
}

We can also see that the CreateRecipe RPC has already been added to the Msg service:

recipes/proto/recipes/recipes/tx.proto
service Msg {
rpc CreateRecipe(MsgCreateRecipe) returns (MsgCreateRecipeResponse);
}

📕 Define messages logic

Navigate to recipes/x/recipes/keeper/msg_server_create_recipe.go. -For our recipes chain, we want the dish and ingredients to be written -to the blockchain’s state as a new recipe. Add the following code to -the CreateRecipe function underneath the imports:

recipes/x/recipes/keeper/msg_server_create_recipe.go
func (k msgServer) CreateRecipe(goCtx context.Context, msg *types.MsgCreateRecipe) (*types.MsgCreateRecipeResponse, error) {
// Get the context
ctx := sdk.UnwrapSDKContext(goCtx)

// Create variable of type Recipe
var recipe = types.Recipe{
Creator: msg.Creator,
Dish: msg.Dish,
Ingredients: msg.Ingredients,
}

// Add a recipe to the store and get back the ID
id := k.AppendRecipe(ctx, recipe)

// Return the ID of the recipe
return &types.MsgCreateRecipeResponse{Id: id}, nil
}

You will see errors in your text editor, which we will resolve in the next step.

🔁 Keepers

📗 Define Recipe type and AppendRecipe keeper method

Create a file recipes/proto/recipes/recipes/recipe.proto and -define the Recipe message:

recipes/proto/recipes/recipes/recipe.proto
syntax = "proto3";

package recipes.recipes;

option go_package = "recipes/x/recipes/types";

message Recipe {
string creator = 1;
uint64 id = 2;
string dish = 3;
string ingredients = 4;
}

📘 Define keeper methods

Now you’ll define your AppendRecipe keeper method.

Create the recipes/x/recipes/keeper/recipe.go file. The -AppendRecipe function is a placeholder to brainstorm how -to implement it:

recipes/x/recipes/keeper/recipe.go
package keeper

import (
"encoding/binary"

"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"

"recipes/x/recipes/types"
)

// func (k Keeper) AppendRecipe() uint64 {
// count := k.GetRecipeCount()
// store.Set()
// k.SetRecipeCount()
// return count
// }

Add these prefixes to the recipes/x/recipes/types/keys.go file -in the const and add a comment for your reference:

recipes/x/recipes/types/keys.go
const (
//...

// Keep track of the index of recipes
RecipeKey = "Recipe-value-"
RecipeCountKey = "Recipe-count-"
)

Next, implement GetRecipeCount in the recipes/x/recipes/keeper/recipe.go file:

recipes/x/recipes/keeper/recipe.go
func (k Keeper) GetRecipeCount(ctx sdk.Context) uint64 {
// Get the store using storeKey (which is "recipes") and RecipeCountKey (which is "Recipe-count-")
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeCountKey))

// Convert the RecipeCountKey to bytes
byteKey := []byte(types.RecipeCountKey)

// Get the value of the count
bz := store.Get(byteKey)

// Return zero if the count value is not found (for example, it's the first recipe)
if bz == nil {
return 0
}

// Convert the count into a uint64
return binary.BigEndian.Uint64(bz)
}

And then SetRecipeCount:

recipes/x/recipes/keeper/recipe.go
func (k Keeper) SetRecipeCount(ctx sdk.Context, count uint64) {
// Get the store using storeKey (which is "recipes") and RecipeCountKey (which is "Recipe-count-")
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeCountKey))

// Convert the RecipeCountKey to bytes
byteKey := []byte(types.RecipeCountKey)

// Convert count from uint64 to string and get bytes
bz := make([]byte, 8)
binary.BigEndian.PutUint64(bz, count)

// Set the value of Recipe-count- to count
store.Set(byteKey, bz)
}

Now you’re ready to implement the AppendRecipe function at -the top of the file above GetRecipeCount and SetRecipeCount:

recipes/x/recipes/keeper/recipe.go
func (k Keeper) AppendRecipe (ctx sdk.Context, recipe types.Recipe) uint64 {
// Get the current number of recipes in the store
count := k.GetRecipeCount(ctx)

// Assign an ID to the recipe based on the number of recipes in the store
recipe.Id = count

// Get the store
store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecipeKey))

// Convert the recipe ID into bytes
byteKey := make([]byte, 8)
binary.BigEndian.PutUint64(byteKey, recipe.Id)

// Marshal the recipe into bytes
appendedValue := k.cdc.MustMarshal(&recipe)

// Insert the recipe bytes using recipe ID as a key
store.Set(byteKey, appendedValue)

// Update the recipe count
k.SetRecipeCount(ctx, count+1)
return count
}

Now you have implemented all the code required to create -new recipes and store them on-chain. When a transaction that -contains a message type MsgCreateRecipe is broadcast, the -message is routed to the recipes module.

  • k.CreateRecipe calls AppendRecipe, which gets the recipe -count, adds a recipe using the count as the ID, increments the -count, and returns the ID

🍽️ Querying recipes

🖥 Query recipes

In order to query your recipes, scaffold a query with Ignite:

ignite scaffold query dishes --response dish,ingredients

A response on a successful scaffold will look like this:

modify proto/recipes/recipes/query.proto
modify x/recipes/client/cli/query.go
create x/recipes/client/cli/query_dishes.go
create x/recipes/keeper/query_dishes.go

🎉 Created a query `dishes`.

In the proto/recipes/recipes/query.proto file import:

proto/recipes/recipes/query.proto
import "recipes/recipes/recipe.proto";

Add pagination to the recipe request:

proto/recipes/recipes/query.proto
message QueryDishesRequest {
// Adding pagination to request
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}

Add pagination to the recipe response:

proto/recipes/recipes/query.proto
message QueryDishesResponse {
// Returning a list of recipes
repeated Recipe Recipe = 1;

// Adding pagination to response
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

In order to implement recipe querying logic in -recipes/x/recipes/keeper/query_dishes.go, -delete the file contents and replace them with:

recipes/x/recipes/keeper/query_dishes.go
package keeper

import (
"context"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"recipes/x/recipes/types"
)

func (k Keeper) Dishes(c context.Context, req *types.QueryDishesRequest) (*types.QueryDishesResponse, error) {
// Throw an error if request is nil
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}

// Define a variable that will store a list of recipes
var dishes []*types.Recipe

// Get context with the information about the environment
ctx := sdk.UnwrapSDKContext(c)

// Get the key-value module store using the store key (in our case store key is "chain")
store := ctx.KVStore(k.storeKey)

// Get the part of the store that keeps recipes (using recipe key, which is "Recipe-value-")
recipeStore := prefix.NewStore(store, []byte(types.RecipeKey))

// Paginate the recipes store based on PageRequest
pageRes, err := query.Paginate(recipeStore, req.Pagination, func(key []byte, value []byte) error {
var dish types.Recipe
if err := k.cdc.Unmarshal(value, &dish); err != nil {
return err
}

dishes = append(dishes, &dish)

return nil
})

// Throw an error if pagination failed
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

// Return a struct containing a list of recipes and pagination info
return &types.QueryDishesResponse{Recipe: dishes, Pagination: pageRes}, nil
}

👩‍🍳 Running the recipes rollup

✨ Run a Celestia light node

Follow instructions to install and start your Celestia Data Availalbility -layer Light Node selecting the network that you previously used. You can -find instructions to install and run the node here.

After you have Go and Ignite CLI installed, and your Celestia Light -Node running on your machine, you're ready to build, test, and launch your own -sovereign rollup.

Be sure you have initialized your node before trying to start it. -When starting your node, remember to enable the gateway. -Your start command should look similar to:

celestia light start --core.ip https://rpc-blockspacerace.pops.one --gateway --gateway.addr 127.0.0.1 --gateway.port 26659 --p2p.network blockspacerace

light-node.png

🗞️ Start the recipes rollup

We have a handy init.sh found in this repo -here.

We can copy it over to our directory with the following commands:

# From inside the `recipes` directory
wget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/recipes/init.sh

This copies over our init.sh script to initialize our -Recipes Rollup.

You can view the contents of the script to see how we -initialize the Recipes Rollup.

caution

Before starting our rollup, we'll need to find -and change FlagDisableIAVLFastNode to FlagIAVLFastNode:

recipes/cmd/recipesd/cmd/root.go
baseapp.SetIAVLFastNode(cast.ToBool(appOpts.Get(server.FlagIAVLFastNode))),

🟢 From your project working directory (recipes/), start the chain with:

bash init.sh

With that, we have kickstarted our recipesd network!

recipe-start.gif

Open another teminal instance. Now, create your first -recipe in the command line by sending a transaction from recipes-key, -when prompted, confirm the transaction by entering y:

recipesd tx recipes create-recipe salad "spinach, mandarin oranges, sliced almonds, smoked gouda, citrus vinagrette" --from recipes-key --keyring-backend test

recipes.gif

⌨️ Query your recipes with the CLI

To query all of the on-chain recipes:

recipesd q recipes dishes

query.gif

🎉 Congratulations, again! You have now successfully built a recipe book rollup.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/index.html b/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/index.html deleted file mode 100644 index cd2cc7a04..000000000 --- a/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -🔄 How to restart your rollup | Rollkit - - - - - - - - - -
-

🔄 How to restart your rollup

This guide will teach you how to restart your Rollkit rollup in the case that the node that you are using to post blocks to your DA and consensus layer runs out of funds (tokens).

💻 Setup of this example

In this example, we're using Celestia's Blockspacerace testnet and running an Ethermint chain. In this example, our Celestia DA light node ran out of Blockspace Race TIA and we are unable to post new blocks to Celestia due to a Code: 19 error. This error is defined by Cosmos SDK as:

// ErrTxInMempoolCache defines an ABCI typed error where a tx already exists in the mempool.
ErrTxInMempoolCache = Register(RootCodespace, 19, "tx already in mempool")

In order to get around this error, and the same error on other Rollkit rollups, you will need to re-fund your Celestia account and increase the gas fee. This will override the transaction that is stuck in the mempool.

If you top up the balance of your node and don't increase the gas fee, you will still encounter the Code: 19 error because there is a transaction (posting block to DA) that is duplicate to one that already exists. In order to get around this, you'll need to increase the gas fee and restart the chain.

🟠 Errors in this example

This is what the errors will look like if your DA node runs out of funding or you restart the chain without changing the gas fee:

4:51PM INF submitting block to DA layer height=28126 module=BlockManager
4:51PM ERR DA layer submission failed error="Codespace: 'sdk', Code: 19, Message: " attempt=1 module=BlockManager
4:51PM ERR DA layer submission failed Error="Codespace: 'sdk', Code: 19, Message: " attempt=2 module=BlockManager
4:51PM ERR DA layer submission failed error="Codespace: 'sdk', Code: 19, Message: " attempt=3 module=BlockManager
4:51PM ERR DA layer submission failed error="Codespace: 'sdk', Code: 19, Message: " attempt=4 module=BlockManager
4:51PM ERR DA layer submission failed error="Codespace: 'sdk', Code: 19, Message: " attempt=5 module=BlockManager
4:51PM ERR DA layer submission failed error="Codespace: 'sdk', Code: 19, Message: " attempt=6 module=BlockManager

💰 Re-fund your account

First, you'll need to send more tokens to the account running your Celestia node. If you didn't keep track of your key, you can run the following to get your address:

cd $HOME && cd celestia-node
./cel-key list --keyring-backend test --node.type light --p2p.network <network>

🛑 Stopping your rollup

You can stop your Ethermint chain (or other Rollkit rollup) by using Control + C in your terminal where the node is running.

🔁 Restarting your rollup

First, be sure that you are using the same Namespace ID as you were before your Celestia node ran out of tokens.

Next, you'll need to fetch the current block height and set the variable accordingly for your start command. In this example, we're using Blockspace Race testnet on Celestia for DA and consensus:

DA_BLOCK_HEIGHT=$(curl https://rpc-blockspacerace.pops.one/block | jq -r '.result.block.header.height')

⛽ Increase the gas fee

To reiterate, before restarting the chain, you will need to increase the gas fee in order to avoid a Code: 19 error:

ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config='{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6900}' --rollkit.namespace_id 8BE3175CBF305BC2 --rollkit.da_start_height $DA_BLOCK_HEIGHT

🛢️ Reduce gas fee & restart again

In order to save your TIA, we also recommend stopping the chain with Control + C, changing the gas fee back to the default (in our case, 6000 utia), fetching current block height, and restarting the chain:

ethermintd start --rollkit.aggregator true --rollkit.da_layer celestia --rollkit.da_config='{"base_url":"http://localhost:26659","timeout":60000000000,"gas_limit":6000000,"fee":6000}' --rollkit.namespace_id 8BE3175CBF305BC2 --rollkit.da_start_height $DA_BLOCK_HEIGHT

🎊 Congrats! You've successfully restarted your Rollkit rollup after running out of TIA.

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/docs/tutorials/wordle/index.html b/pr-preview/pr-192/docs/tutorials/wordle/index.html deleted file mode 100644 index 48bbc74af..000000000 --- a/pr-preview/pr-192/docs/tutorials/wordle/index.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - -🕹️ Wordle app | Rollkit - - - - - - - - - -
-

🕹️ Wordle app

wordle-app

This tutorial guide will go over building a cosmos-sdk app -for Rollkit, the Sovereign-Rollup implementation of -Tendermint, for the popular game Wordle.

This tutorial will go over how to setup Rollkit -in the Ignite CLI and use it to build the game. -The tutorial will go over the simple design, -as well as conclude with future implementations and ideas -to extend this codebase.

note

This tutorial will explore developing with Rollkit, -which is still in Alpha stage. If you run into bugs, please write a Github -Issue ticket -or let us know in our Telegram.

caution

The script for this tutorial is built for Celestia's -Blockspacerace testnet. -If you choose to use Mocha testnet or Arabica devnet, -you will need to modify the script manually.

💻 Pre-requisites

Given this tutorial is targeted for developers who are experienced -in Cosmos-SDK, we recommend you go over the following tutorials -in Ignite to understand all the different components in Cosmos-SDK before -proceeding with this tutorial.

You do not have to do those guides in order to follow this Wordle tutorial, -but doing so helps you understand the architecture of Cosmos-SDK better.

📖 Design implementation

The rules of Wordle are simple: You have to guess the word of the day.

Key Points to Consider:

  • The word is a five-letter word.
  • You have 6 guesses.
  • Every 24 hours, there’s a new word.

The GUI for Wordle shows you a few indicators: a -green highlight on a letter in a certain position -means that’s the correct letter for the Wordle -in the right position. A yellow highlight means -it’s a correct letter for the Wordle included in -the wrong position. A grey highlight means the letter -isn’t part of the Wordle.

For simplicity of the design, we will avoid those -hints, although there are ways to extend this codebase -to implement that, which we will show at the end.

In this current design, we implement the following rules:

  • 1 Wordle can be submitted per day
  • Every address will have 6 tries to guess the word
  • It must be a five-letter word.
  • Whoever guesses the word correctly before their -6 tries are over gets an award of 100 WORDLE tokens.

We will go over the architecture to achieve this further -in the guide. But for now, we will get started setting up -our development environment.

📋 Table of contents for this tutorial

The following tutorial is broken down into the following -sections:

  1. Ignite and Chain Scaffolding
  2. Installing Rollkit
  3. Modules
  4. Messages
  5. Types
  6. Keepers
  7. Running Wordle

⛓️ Ignite and scaffolding the wordle chain

🔥 Ignite

Ignite is an amazing CLI tool to help us get started building -our own blockchains for cosmos-sdk apps. It provides lots of -power toolings and scaffoldings for adding messages, types, -and modules with a host of cosmos-sdk libraries provided.

You can read more about Ignite here.

To install Ignite, you can run this command in your terminal:

curl https://get.ignite.com/cli@v0.26.1! | bash
sudo mv ignite /usr/local/bin/

This installs Ignite CLI in your local machine. -This tutorial uses a MacOS but it should work for Windows. -For Windows users, check out the Ignite docs on installation -for Windows machines.

Now, refresh your terminal using source or open a new terminal -session for the change to take place.

If you run the following:

ignite --help

You should see an output of help commands meaning Ignite -was installed successfully!

⛓️ Scaffolding the wordle chain

Now, comes the fun part, creating a new blockchain! With Ignite, -the process is pretty easy and straightforward.

Ignite CLI comes with several scaffolding commands that are -designed to make development more straightforward by creating -everything you need to build your blockchain.

First, we will use Ignite CLI to build the foundation of a fresh -Cosmos SDK blockchain. Ignite minimizes how much blockchain code -you must write yourself. If you are coming from the EVM-world, think of -Ignite as a Cosmos-SDK version of Foundry or Hardhat but specifically -designed to build blockchains.

We first run the following command to setup our project for -our new blockchain, Wordle.

ignite scaffold chain wordle --no-module

This command scaffolds a new chain directory called wordle -in your local directory from which you ran the command. Notice -that we passed the --no-module flag, this is because we will be -creating the module after.

🗂️ Wordle directory

Now, it’s time to enter the directory:

cd wordle

Inside you will see several directories and architecture for -your cosmos-sdk blockchain.

File/directoryPurpose
app/Files that wire together the blockchain. The most important file is app.go that contains type definition of the blockchain and functions to create and initialize it.
cmd/The main package responsible for the CLI of compiled binary.
docs/Directory for project documentation. By default, an OpenAPI spec is generated.
proto/Protocol buffer files describing the data structure.
testutil/Helper functions for testing.
vue/A Vue 3 web app template.
x/Cosmos SDK modules and custom modules.
config.ymlA configuration file for customizing a chain in development.
readme.mdA readme file for your sovereign application-specific blockchain project.

Going over each one is outside the scope of this guide, but we encourage you -to read about it here.

Most of the tutorial work will happen inside the x directory.

🛠️ Setting up Rollkit

Before we continue with building our Wordle App, we need to set up -Rollkit on our codebase.

🗞️ Installing Rollkit

Run the following command inside the wordle directory.

go mod edit -replace github.com/cosmos/cosmos-sdk=github.com/rollkit/cosmos-sdk@v0.46.7-rollkit-v0.7.3-no-fraud-proofs
go mod edit -replace github.com/tendermint/tendermint=github.com/celestiaorg/tendermint@v0.34.22-0.20221202214355-3605c597500d
go mod tidy
go mod download

With that, we have Rollkit changes added to the project directory. Now, -let's build the Wordle app!

✨ Creating the wordle module

For the Wordle module, we can add dependencies offered by Cosmos-SDK.

From the Cosmos-SDK docs, a module -is defined as the following:

In a Cosmos SDK blockchain, application-specific logic -is implemented in separate modules. Modules keep code easy -to understand and reuse. Each module contains its own message -and transaction processor, while the Cosmos SDK is responsible -for routing each message to its respective module.

Many modules exist for slashing, validating, auth.

🔖 Scaffolding a module

We will be using the bank module dependency for transactions.

From the Cosmos-SDK docs, the bank -module is defined as the following:

The bank module is responsible for handling multi-asset coin -transfers between accounts and tracking special-case pseudo-transfers -which must work differently with particular kinds of accounts -(notably delegating/undelegating for vesting accounts). It exposes -several interfaces with varying capabilities for secure interaction -with other modules which must alter user balances.

We build the module with the bank dependency with the following command:

ignite scaffold module wordle --dep bank

This will scaffold the Wordle module to our Wordle Chain project.

✉️ Messages

Messages allow us to process and submit information to our specific module.

From the Cosmos-SDK docs, messages -are:

In the Cosmos SDK, messages are objects that are contained -in transactions to trigger state transitions. Each Cosmos SDK -module defines a list of messages and how to handle them.

For messages for Wordle, given our initial design, we will -make 2 messages with ignite.

  • The first one is: SubmitWordle and it only passes the Wordle of the Day.
  • The second one is: SubmitGuess and it attempts to guess the submitted -wordle. It also passes a word as a guess.

With these initial designs, we can start creating our messages!

💬 Scaffolding a message

To create the SubmitWordle message, we run the following command:

ignite scaffold message submit-wordle word

This creates the submit-wordle message that takes in word as a parameter.

We now create the final message, SubmitGuess:

ignite scaffold message submit-guess word

Here, we are passing a word as a guess with submit-guess.

🎨 Wordle types

For the next steps, we will be creating types to be used by -the messages we created.

🏗️ Scaffolding wordle types

ignite scaffold map wordle word submitter --no-message

This type is a map called Wordle with two values of -word and submitter. submitter is the address of the -person that submitted the Wordle.

The second type is the Guess type. It allows us to store -the latest guess for each address that submitted a solution.

ignite scaffold map guess word submitter count --no-message

Here, we are also storing count to count how many guesses -this address submitted.

🔐 Keeper functions

Now it’s time to implement the Keeper functions for each -message. From the Cosmos-SDK docs, Keeper -is defined as the following:

The main core of a Cosmos SDK module is a piece called the keeper. -The keeper handles interactions with the store, has references -to other keepers for cross-module interactions, and contains most -of the core functionality of a module.

Keeper is an abstraction on Cosmos that allows us -to interact with the Key-Value store and change the state -of the blockchain.

Here, it will help us outline the logic for each message we create.

📤 SubmitWordle function

We first start with the SubmitWordle function.

Open up the following file: x/wordle/keeper/msg_server_submit_wordle.go

Inside the following, replace the current code with the following code, -which we will go over in a bit:

x/wordle/keeper/msg_server_submit_wordle.go
package keeper

import (
"context"
"crypto/sha256"
"encoding/hex"
"wordle/x/wordle/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"time"
"unicode"
"github.com/tendermint/tendermint/crypto"
)

func (k msgServer) SubmitWordle(goCtx context.Context, msg *types.MsgSubmitWordle) (*types.MsgSubmitWordleResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// Check to See the Wordle is 5 letters
if len(msg.Word) != 5 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle Must Be A 5 Letter Word")
}
// Check to See Only Alphabets Are Passed for the Wordle
if !(IsLetter(msg.Word)) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle Must Only Consist Of Letters In The Alphabet")
}

// Use Current Day to Create The Index of the Newly-Submitted Wordle of the Day
currentTime := time.Now().Local()
var currentTimeBytes = []byte(currentTime.Format("2006-01-02"))
var currentTimeHash = sha256.Sum256(currentTimeBytes)
var currentTimeHashString = hex.EncodeToString(currentTimeHash[:])
// Hash The Newly-Submitted Wordle of the Day
var submittedSolutionHash = sha256.Sum256([]byte(msg.Word))
var submittedSolutionHashString = hex.EncodeToString(submittedSolutionHash[:])

var wordle = types.Wordle{
Index: currentTimeHashString,
Word: submittedSolutionHashString,
Submitter: msg.Creator,
}

// Try to Get Wordle From KV Store Using Current Day as Key
// This Helps ensure only one Wordle is submitted per day
_, isFound := k.GetWordle(ctx, currentTimeHashString)
if isFound {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle of the Day is Already Submitted")
}
// Write Wordle to KV Store
k.SetWordle(ctx, wordle)
reward := sdk.Coins{sdk.NewInt64Coin("token", 100)}
// Escrow Reward
submitterAddress, _ := sdk.AccAddressFromBech32(msg.Creator)
moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName)))
err := k.bankKeeper.SendCoins(ctx, submitterAddress, moduleAcct, reward)
if err != nil {
return nil, err
}
return &types.MsgSubmitWordleResponse{}, nil
}

func IsLetter(s string) bool {
for _, r := range s {
if !unicode.IsLetter(r) {
return false
}
}
return true
}

Here in the SubmitWordle Keeper function, we are doing a few things:

  • We first ensure that a word submitted for Wordle of the Day is -5 letters long and only uses alphabets. That means no integers can -be submitted in the string.
  • We then create a hash from the current day the moment the Wordle was -submitted. We set this hash to the index of the Wordle type. This -allows us to look up any guesses for this Wordle for subsequent -guesses, which we will go over next.
  • We then check if the index for today’s date is currently empty or -not. If it’s not empty, this means a Wordle has already been -submitted. Remember, only one wordle can be submitted per -day. Everyone else has to guess the submitted wordle.
  • We also have a helper function in there to check if a string only -contains alphabet characters.

SubmitGuess function

The next Keeper function we will add is the following: -x/wordle/keeper/msg_server_submit_guess.go

Open that file and replace its contents with the following code, which we will -explain in a bit:

x/wordle/keeper/msg_server_submit_guess.go
package keeper

import (
"context"
"crypto/sha256"
"encoding/hex"
"wordle/x/wordle/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"strconv"
"time"
"github.com/tendermint/tendermint/crypto"
)

func (k msgServer) SubmitGuess(goCtx context.Context, msg *types.MsgSubmitGuess) (*types.MsgSubmitGuessResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// Check Word is 5 Characters Long
if len(msg.Word) != 5 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Guess Must Be A 5 Letter Word!")
}

// Check String Contains Alphabet Letters Only
if !(IsLetter(msg.Word)) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Guess Must Only Consist of Alphabet Letters!")
}

// Get Current Day to Pull Up Wordle of That Day As A Hash
currentTime := time.Now().Local()
var currentTimeBytes = []byte(currentTime.Format("2006-01-02"))
var currentTimeHash = sha256.Sum256(currentTimeBytes)
var currentTimeHashString = hex.EncodeToString(currentTimeHash[:])
wordle, isFound := k.GetWordle(ctx, currentTimeHashString)
if !isFound {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Wordle of The Day Hasn't Been Submitted Yet. Feel Free to Submit One!")
}

// We Convert Current Day and Guesser to A Hash To Use As An Index For Today's Guesses For That Guesser
// That Way, A Person Can Guess 6 Times A Day For Each New Wordle Created
var currentTimeGuesserBytes = []byte(currentTime.Format("2006-01-02") + msg.Creator)
var currentTimeGuesserHash = sha256.Sum256(currentTimeGuesserBytes)
var currentTimeGuesserHashString = hex.EncodeToString(currentTimeGuesserHash[:])
// Hash The Guess To The Wordle
var submittedSolutionHash = sha256.Sum256([]byte(msg.Word))
var submittedSolutionHashString = hex.EncodeToString(submittedSolutionHash[:])

// Get the Latest Guess entry for this Submitter for the current Wordle of the Day
var count int
guess, isFound := k.GetGuess(ctx, currentTimeGuesserHashString)
if isFound {
// Check if Submitter Reached 6 Tries
if guess.Count == strconv.Itoa(6) {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "You Have Guessed The Maximum Amount of Times for The Day! Try Again Tomorrow With A New Wordle.")
}
currentCount, err := strconv.Atoi(guess.Count)
if err != nil {
panic(err)
}
count = currentCount
} else {
// Initialize Count Value If No Entry Exists for this Submitter for Today's Wordle
count = 0
}
// Increment Guess Count
count += 1
var newGuess = types.Guess{
Index: currentTimeGuesserHashString,
Submitter: msg.Creator,
Word: submittedSolutionHashString,
Count: strconv.Itoa(count),
}
// Remove Current Guess Entry to be Updated With New Entry
k.RemoveGuess(ctx, currentTimeGuesserHashString)
// Add New Guess Entry
k.SetGuess(ctx, newGuess)
if !(wordle.Word == submittedSolutionHashString) {
return &types.MsgSubmitGuessResponse{Title: "Wrong Answer", Body: "Your Guess Was Wrong. Try Again"}, nil
} else {
// Setup Reward
reward := sdk.Coins{sdk.NewInt64Coin("token", 100)}
// If Submitter Guesses Correctly
guesserAddress, _ := sdk.AccAddressFromBech32(msg.Creator)
moduleAcct := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName)))
// Send Reward
err := k.bankKeeper.SendCoins(ctx, moduleAcct, guesserAddress, reward)
if err !=nil {
return nil, err
}
return &types.MsgSubmitGuessResponse{Title: "Correct", Body: "You Guessed The Wordle Correctly!"}, nil
}
}

In the above code, we are doing the following things:

  • Here, we are doing initial checks again on the word to ensure -it’s 5 characters and only alphabet characters are used, which -can be refactored in the future or checked within the CLI commands.
  • We then get the Wordle of the Day by getting the hash string of -the current day.
  • Next we create a hash string of current day and the Submitter. -This allows us to create a Guess type with an index that uses the -current day and the address of the submitter. This helps us when we -face a new day and an address wants to guess the new wordle of the day. -The index setup ensures they can continue guessing a new wordle -every day up to the max of 6 tries per day.
  • We then check if that Guess type for the Submitter for today’s -wordle did reach 6 counts. If it hasn’t, we increment the count. -We then check if the guess is correct. We store the Guess type with -the updated count to the state.

📦 Protobuf file

A few files need to be modified for this to work.

The first is proto/wordle/wordle/tx.proto.

Inside this file, fill in the empty MsgSubmitGuessResponse -with the following code:

proto/wordle/tx.proto
message MsgSubmitGuessResponse {
string title = 1;
string body = 2;
}

Next file is x/wordle/types/expected_keepers.go

Here, we need to add the SendCoins method to the BankKeeper -interface in order to allow sending the reward to the right guesser.

x/wordle/types/expected_keepers.go
type BankKeeper interface {
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
}

With that, we implemented all our Keeper functions! Time to -compile the blockchain and take it out for a test drive.

⛓️ Run the wordle chain

🪶 Run a Celestia light node

Follow instructions to install and start your Celestia Data -Availalbility layer Light Node selecting the network that -you had previously used. You can find instructions to install -and run the node here.

After you have Go and Ignite CLI installed, and your Celestia -Light Node running on your machine, you're ready to build, -test, and launch your own sovereign rollup.

🟢 Building and running wordle chain

We have a handy init.sh found in this repo -here.

We can copy it over to our directory with the following commands:

# From inside the `wordle` directory
wget https://raw.githubusercontent.com/rollkit/docs/main/docs/scripts/wordle/init.sh

This copies over our init.sh script to initialize our -Wordle Rollup.

You can view the contents of the script to see how we -initialize the Wordle Rollup.

caution

On some machines, before starting our rollup, we'll need to find -and change FlagIAVLFastNode to FlagDisableIAVLFastNode:

wordle/cmd/wordled/cmd/root.go
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(server.FlagDisableIAVLFastNode))),

You can initialize the script with the following command:

bash init.sh

With that, we have kickstarted our wordled network!

In another window, run the following to submit a Wordle:

wordled tx wordle submit-wordle giant --from wordle-key --keyring-backend test --chain-id wordle -b async -y

NOTE: We are submitting a transaction asynchronously due to avoiding -any timeout errors. With Rollkit as a replacement to Tendermint, we -need to wait for Celestia's Data-Availability network to ensure a block -was included from Wordle, before proceeding to the next block. Currently, -in Rollkit, the single aggregator is not moving forward with the next block -production as long as it is trying to submit the current block to the DA network. -In the future, with leader selection, block production and sync logic improves -dramatically.

This will ask you to confirm the transaction with the following message:

{
"body":{
"messages":[
{
"@type":"/YazzyYaz.wordle.wordle.MsgSubmitWordle",
"creator":"cosmos17lk3fgutf00pd5s8zwz5fmefjsdv4wvzyg7d74",
"word":"giant"
}
],
"memo":"",
"timeout_height":"0",
"extension_options":[
],
"non_critical_extension_options":[
]
},
"auth_info":{
"signer_infos":[
],
"fee":{
"amount":[
],
"gas_limit":"200000",
"payer":"",
"granter":""
}
},
"signatures":[
]
}

Cosmos-SDK will ask you to confirm the transaction here:

confirm transaction before signing and broadcasting [y/N]:

Confirm with a Y.

You will then get a response with a transaction hash as shown here:

code: 0
codespace: ""
data: ""
events: []
gas_used: "0"
gas_wanted: "0"
height: "0"
info: ""
logs: []
raw_log: ""
timestamp: ""
tx: null
txhash: F159E11116EC9505FC2C0D97E605357FEC0F3DAE06B57BFB17EA6A548905043E

Note, this does not mean the transaction was included in the block yet. -Let's query the transaction hash to check whether it has been included in -the block yet or if there are any errors.

wordled query tx --type=hash F159E11116EC9505FC2C0D97E605357FEC0F3DAE06B57BFB17EA6A548905043E --chain-id wordle --output json | jq -r '.raw_log'

This should display an output like the following:

[{"events":[{"type":"message","attributes":[{"key":"action","value":"submit_wordle"
}]}]}]

Test out a few things for fun:

wordled tx wordle submit-guess 12345 --from wordle-key --keyring-backend test --chain-id wordle -b async -y

After confirming the transaction, query the txhash -given the same way you did above. You will see the response shows -an Invalid Error because you submitted integers.

Now try:

wordled tx wordle submit-guess ABCDEFG --from wordle-key --keyring-backend test --chain-id wordle -b async -y

After confirming the transaction, query the txhash given the same -way you did above. You will see the response shows -an Invalid Error because you submitted a word larger than 5 characters.

Now try to submit another wordle even though one was already submitted

wordled tx wordle submit-wordle meter --from wordle-key --keyring-backend test --chain-id wordle -b async -y

After submitting the transactions and confirming, query the txhash -given the same way you did above. You will get an error that a wordle -has already been submitted for the day.

Now let’s try to guess a five letter word:

wordled tx wordle submit-guess least --from wordle-key --keyring-backend test --chain-id wordle -b async -y

After submitting the transactions and confirming, query the txhash -given the same way you did above. Given you didn’t guess the correct -word, it will increment the guess count for wordle-key's account.

We can verify this by querying the list:

wordled q wordle list-guess --output json

This outputs all Guess objects submitted so far, with the index -being today’s date and the address of the submitter.

With that, we implemented a basic example of Wordle using -Cosmos-SDK and Ignite and Rollkit. Read on to how you can -extend the code base.

🔮 Extending in the future

You can extend the codebase and improve this tutorial by checking -out the repository here.

There are many ways this codebase can be extended:

  1. You can improve messaging around when you guess the correct word.
  2. You can hash the word prior to submitting it to the chain, -ensuring the hashing is local so that it’s not revealed via -front-running by others monitoring the plaintext string when -it’s submitted on-chain.
  3. You can improve the UI in terminal using a nice interface for -Wordle. Some examples are here.
  4. You can improve current date to stick to a specific timezone.
  5. You can create a bot that submits a wordle every day at a specific time.
  6. You can create a vue.js front-end with Ignite using example open-source -repositories here and here.
- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/fonts/Inter/Inter-Light.ttf b/pr-preview/pr-192/fonts/Inter/Inter-Light.ttf deleted file mode 100644 index b9c460dcc..000000000 Binary files a/pr-preview/pr-192/fonts/Inter/Inter-Light.ttf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Inter/Inter-Regular.ttf b/pr-preview/pr-192/fonts/Inter/Inter-Regular.ttf deleted file mode 100644 index cc73944ac..000000000 Binary files a/pr-preview/pr-192/fonts/Inter/Inter-Regular.ttf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Bold.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Bold.otf deleted file mode 100644 index d9fae2ea6..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Bold.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-BoldOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-BoldOblique.otf deleted file mode 100644 index e90ef0907..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-BoldOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBold.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBold.otf deleted file mode 100644 index 5661e9dd4..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBold.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBoldOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBoldOblique.otf deleted file mode 100644 index ba5fe2b47..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraBoldOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLight.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLight.otf deleted file mode 100644 index a48534e99..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLight.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLightOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLightOblique.otf deleted file mode 100644 index 08763e23b..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ExtraLightOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Light.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Light.otf deleted file mode 100644 index 40975aca5..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Light.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-LightOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-LightOblique.otf deleted file mode 100644 index f550dffcd..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-LightOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Medium.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Medium.otf deleted file mode 100644 index b432b8fa5..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Medium.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-MediumOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-MediumOblique.otf deleted file mode 100644 index fe3249e3c..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-MediumOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Oblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Oblique.otf deleted file mode 100644 index 40ccec1f1..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Oblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Regular.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Regular.otf deleted file mode 100644 index a99fe54e3..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Regular.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBold.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBold.otf deleted file mode 100644 index 7840159e1..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBold.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBoldOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBoldOblique.otf deleted file mode 100644 index 1c796b3d7..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-SemiBoldOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Thin.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Thin.otf deleted file mode 100644 index e16b21bd0..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-Thin.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ThinOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ThinOblique.otf deleted file mode 100644 index 9170568d5..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-ThinOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLight.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLight.otf deleted file mode 100644 index 09b28f012..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLight.otf and /dev/null differ diff --git a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLightOblique.otf b/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLightOblique.otf deleted file mode 100644 index 3b78e35a6..000000000 Binary files a/pr-preview/pr-192/fonts/Ruberoid/Ruberoid-UltraLightOblique.otf and /dev/null differ diff --git a/pr-preview/pr-192/img/1f4c8.svg b/pr-preview/pr-192/img/1f4c8.svg deleted file mode 100644 index cbf108fc0..000000000 --- a/pr-preview/pr-192/img/1f4c8.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pr-preview/pr-192/img/1f512.svg b/pr-preview/pr-192/img/1f512.svg deleted file mode 100644 index 38653086f..000000000 --- a/pr-preview/pr-192/img/1f512.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/pr-preview/pr-192/img/1f680.svg b/pr-preview/pr-192/img/1f680.svg deleted file mode 100644 index 8658d4397..000000000 --- a/pr-preview/pr-192/img/1f680.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pr-preview/pr-192/img/2699.svg b/pr-preview/pr-192/img/2699.svg deleted file mode 100644 index 635ca02f2..000000000 --- a/pr-preview/pr-192/img/2699.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pr-preview/pr-192/img/Rollkit-og.png b/pr-preview/pr-192/img/Rollkit-og.png deleted file mode 100644 index 941d1a9d3..000000000 Binary files a/pr-preview/pr-192/img/Rollkit-og.png and /dev/null differ diff --git a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-1.png b/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-1.png deleted file mode 100644 index a6e6635f2..000000000 Binary files a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-1.png and /dev/null differ diff --git a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-2.png b/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-2.png deleted file mode 100644 index 15302188e..000000000 Binary files a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin-2.png and /dev/null differ diff --git a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin.png b/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin.png deleted file mode 100644 index 115d5f50d..000000000 Binary files a/pr-preview/pr-192/img/bitcoin-rollkit/rollkit-bitcoin.png and /dev/null differ diff --git a/pr-preview/pr-192/img/docusaurus.png b/pr-preview/pr-192/img/docusaurus.png deleted file mode 100644 index f458149e3..000000000 Binary files a/pr-preview/pr-192/img/docusaurus.png and /dev/null differ diff --git a/pr-preview/pr-192/img/favicon.ico b/pr-preview/pr-192/img/favicon.ico deleted file mode 100644 index 29ab6a5ef..000000000 Binary files a/pr-preview/pr-192/img/favicon.ico and /dev/null differ diff --git a/pr-preview/pr-192/img/introducing-rollkit/comparison-table.png b/pr-preview/pr-192/img/introducing-rollkit/comparison-table.png deleted file mode 100644 index 252ac9095..000000000 Binary files a/pr-preview/pr-192/img/introducing-rollkit/comparison-table.png and /dev/null differ diff --git a/pr-preview/pr-192/img/introducing-rollkit/rollkit-blog-cover.png b/pr-preview/pr-192/img/introducing-rollkit/rollkit-blog-cover.png deleted file mode 100644 index 8634814ae..000000000 Binary files a/pr-preview/pr-192/img/introducing-rollkit/rollkit-blog-cover.png and /dev/null differ diff --git a/pr-preview/pr-192/img/introducing-rollkit/rollkit-lego.png b/pr-preview/pr-192/img/introducing-rollkit/rollkit-lego.png deleted file mode 100644 index dd0d72027..000000000 Binary files a/pr-preview/pr-192/img/introducing-rollkit/rollkit-lego.png and /dev/null differ diff --git a/pr-preview/pr-192/img/lets-roll/lets-roll.jpg b/pr-preview/pr-192/img/lets-roll/lets-roll.jpg deleted file mode 100644 index 72682e907..000000000 Binary files a/pr-preview/pr-192/img/lets-roll/lets-roll.jpg and /dev/null differ diff --git a/pr-preview/pr-192/img/rollkit-blk.svg b/pr-preview/pr-192/img/rollkit-blk.svg deleted file mode 100644 index 68b335014..000000000 --- a/pr-preview/pr-192/img/rollkit-blk.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/img/rollkit-stack/rollkit-abci.png b/pr-preview/pr-192/img/rollkit-stack/rollkit-abci.png deleted file mode 100644 index 2c1ee506f..000000000 Binary files a/pr-preview/pr-192/img/rollkit-stack/rollkit-abci.png and /dev/null differ diff --git a/pr-preview/pr-192/img/rollkit-wht.svg b/pr-preview/pr-192/img/rollkit-wht.svg deleted file mode 100644 index 01ce3d435..000000000 --- a/pr-preview/pr-192/img/rollkit-wht.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pr-preview/pr-192/img/t-flow/transaction-flow.png b/pr-preview/pr-192/img/t-flow/transaction-flow.png deleted file mode 100644 index 50137bc26..000000000 Binary files a/pr-preview/pr-192/img/t-flow/transaction-flow.png and /dev/null differ diff --git a/pr-preview/pr-192/img/toolbox.svg b/pr-preview/pr-192/img/toolbox.svg deleted file mode 100644 index c12ec1beb..000000000 --- a/pr-preview/pr-192/img/toolbox.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/pr-preview/pr-192/img/tutorials/gm/4.png b/pr-preview/pr-192/img/tutorials/gm/4.png deleted file mode 100644 index 8fdc4b750..000000000 Binary files a/pr-preview/pr-192/img/tutorials/gm/4.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/gm/cca-2.png b/pr-preview/pr-192/img/tutorials/gm/cca-2.png deleted file mode 100644 index 251630f43..000000000 Binary files a/pr-preview/pr-192/img/tutorials/gm/cca-2.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/gm/cca-3.png b/pr-preview/pr-192/img/tutorials/gm/cca-3.png deleted file mode 100644 index ef51b418b..000000000 Binary files a/pr-preview/pr-192/img/tutorials/gm/cca-3.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/gm/cca.png b/pr-preview/pr-192/img/tutorials/gm/cca.png deleted file mode 100644 index f93f9e156..000000000 Binary files a/pr-preview/pr-192/img/tutorials/gm/cca.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/light-node.png b/pr-preview/pr-192/img/tutorials/recipes/light-node.png deleted file mode 100644 index b5cf41dd9..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/light-node.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/query.gif b/pr-preview/pr-192/img/tutorials/recipes/query.gif deleted file mode 100644 index 5627a8338..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/query.gif and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/query.png b/pr-preview/pr-192/img/tutorials/recipes/query.png deleted file mode 100644 index 692a403fd..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/query.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/recipe-start.gif b/pr-preview/pr-192/img/tutorials/recipes/recipe-start.gif deleted file mode 100644 index 0a56b7eea..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/recipe-start.gif and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/recipes.gif b/pr-preview/pr-192/img/tutorials/recipes/recipes.gif deleted file mode 100644 index c1e0b4abb..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/recipes.gif and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/recipes/send-tx.png b/pr-preview/pr-192/img/tutorials/recipes/send-tx.png deleted file mode 100644 index 171d284c3..000000000 Binary files a/pr-preview/pr-192/img/tutorials/recipes/send-tx.png and /dev/null differ diff --git a/pr-preview/pr-192/img/tutorials/wordle/wordle.png b/pr-preview/pr-192/img/tutorials/wordle/wordle.png deleted file mode 100644 index cdb62ec05..000000000 Binary files a/pr-preview/pr-192/img/tutorials/wordle/wordle.png and /dev/null differ diff --git a/pr-preview/pr-192/index.html b/pr-preview/pr-192/index.html deleted file mode 100644 index e504f0e66..000000000 --- a/pr-preview/pr-192/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -Build modular with Rollkit | Rollkit - - - - - - - - - -
-

Shared security

Rollups inherit security from the consensus and data availability layer

Scalable

With off-chain execution, rollups have their own dedicated computational resources

Flexible

Freedom to configure the execution environment and other components

Easy to deploy

Deploy a rollup with only a few terminal commands

- - - - \ No newline at end of file diff --git a/pr-preview/pr-192/sitemap.xml b/pr-preview/pr-192/sitemap.xml deleted file mode 100644 index e924515a4..000000000 --- a/pr-preview/pr-192/sitemap.xml +++ /dev/null @@ -1 +0,0 @@ -https://rollkit.dev/pr-preview/pr-192/blog/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/archive/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/introducing-rollkit/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/lets-roll-community-call/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/sovereign-rollups-on-bitcoin/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/tags/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/tags/bitcoin/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/tags/celestia/weekly0.5https://rollkit.dev/pr-preview/pr-192/blog/tags/rollkit/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/category/advanced/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/category/beginner/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/category/intermediate/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/category/tutorials/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/intro/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/rollkit-stack/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/transaction-flow/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/bitcoin/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/building-and-deploying-a-rollup/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/cosmwasm/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/ethermint/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/gm-world-frontend/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/gm-world/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/recipe-book/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/restart-rollkit-rollup/weekly0.5https://rollkit.dev/pr-preview/pr-192/docs/tutorials/wordle/weekly0.5https://rollkit.dev/pr-preview/pr-192/weekly0.5 \ No newline at end of file