diff --git a/404.html b/404.html index 6f432bdb1..3e581a815 100644 --- a/404.html +++ b/404.html @@ -15,7 +15,7 @@ - + @@ -43,7 +43,7 @@ GitHub (opens new window) GitHub - (opens new window)

404 - Not Found

There's nothing here.
+ (opens new window)

404 - Not Found

That's a Four-Oh-Four.
Take me home.
- + diff --git a/assets/img/blinded-path.2f9b76cf.svg b/assets/img/blinded-path.2f9b76cf.svg new file mode 100644 index 000000000..7939fcca5 --- /dev/null +++ b/assets/img/blinded-path.2f9b76cf.svg @@ -0,0 +1 @@ + diff --git a/assets/img/offer-metadata.45a2a1cf.svg b/assets/img/offer-metadata.45a2a1cf.svg new file mode 100644 index 000000000..f28c04b54 --- /dev/null +++ b/assets/img/offer-metadata.45a2a1cf.svg @@ -0,0 +1 @@ + diff --git a/assets/img/offers-flow.ccc79cd7.svg b/assets/img/offers-flow.ccc79cd7.svg new file mode 100644 index 000000000..cd21e16fe --- /dev/null +++ b/assets/img/offers-flow.ccc79cd7.svg @@ -0,0 +1 @@ + diff --git a/assets/img/qr-codes.58a16df5.png b/assets/img/qr-codes.58a16df5.png new file mode 100644 index 000000000..0ee808ec6 Binary files /dev/null and b/assets/img/qr-codes.58a16df5.png differ diff --git a/assets/js/1.c628fb9b.js b/assets/js/1.0a31852e.js similarity index 99% rename from assets/js/1.c628fb9b.js rename to assets/js/1.0a31852e.js index c4ea6e912..bd6ae56b1 100644 --- a/assets/js/1.c628fb9b.js +++ b/assets/js/1.0a31852e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{252:function(t,e,s){"use strict";s.d(e,"d",(function(){return n})),s.d(e,"a",(function(){return r})),s.d(e,"i",(function(){return a})),s.d(e,"f",(function(){return l})),s.d(e,"g",(function(){return u})),s.d(e,"h",(function(){return c})),s.d(e,"b",(function(){return h})),s.d(e,"e",(function(){return p})),s.d(e,"k",(function(){return d})),s.d(e,"l",(function(){return f})),s.d(e,"c",(function(){return m})),s.d(e,"j",(function(){return b}));s(46);const n=/#.*$/,i=/\.(md|html)$/,r=/\/$/,a=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(n,"").replace(i,"")}function l(t){return a.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function h(t){if(l(t))return t;const e=t.match(n),s=e?e[0]:"",i=o(t);return r.test(i)?t:i+".html"+s}function p(t,e){const s=decodeURIComponent(t.hash),i=function(t){const e=t.match(n);if(e)return e[0]}(e);if(i&&s!==i)return!1;return o(t.path)===o(e)}function d(t,e,s){if(l(e))return{type:"external",path:e};s&&(e=function(t,e,s){const n=t.charAt(0);if("/"===n)return t;if("?"===n||"#"===n)return e+t;const i=e.split("/");s&&i[i.length-1]||i.pop();const r=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,s,n,i=1){if("string"==typeof e)return d(s,e,n);if(Array.isArray(e))return Object.assign(d(s,e[0],n),{title:e[1]});{const r=e.children||[];return 0===r.length&&e.path?Object.assign(d(s,e.path,n),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:r.map(e=>t(e,s,n,i+1)),collapsable:!1!==e.collapsable}}}(t,i,s)):[]}return[]}function g(t){const e=m(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function m(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function b(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},259:function(t,e,s){"use strict";s(328),s(329),s(330),s(46);var n={name:"AlgoliaSearchBox",props:["options"],data:()=>({placeholder:void 0}),watch:{$lang(t){this.update(this.options,t)},options(t){this.update(t,this.$lang)}},mounted(){this.initialize(this.options,this.$lang),this.placeholder=this.$site.themeConfig.searchPlaceholder||""},methods:{initialize(t,e){Promise.all([Promise.all([s.e(0),s.e(3)]).then(s.t.bind(null,369,7)),Promise.all([s.e(0),s.e(3)]).then(s.t.bind(null,370,7))]).then(([s])=>{s=s.default;const{algoliaOptions:n={}}=t;s(Object.assign({},t,{inputSelector:"#algolia-search-input",algoliaOptions:{...n,facetFilters:["lang:"+e].concat(n.facetFilters||[])},handleSelected:(t,e,s)=>{const{pathname:n,hash:i}=new URL(s.url),r=n.replace(this.$site.base,"/"),a=decodeURIComponent(i);this.$router.push(`${r}${a}`)}}))})},update(t,e){this.$el.innerHTML='',this.initialize(t,e)}}},i=(s(332),s(7)),r=Object(i.a)(n,(function(){var t=this._self._c;return t("form",{staticClass:"algolia-search-wrapper search-box",attrs:{id:"search-form",role:"search"}},[t("input",{staticClass:"search-query",attrs:{id:"algolia-search-input",placeholder:this.placeholder}})])}),[],!1,null,null,null).exports,a=s(110),o=s.n(a),l=(t,e,s=null)=>{let n=o()(e,"title","");return o()(e,"frontmatter.tags")&&(n+=" "+e.frontmatter.tags.join(" ")),s&&(n+=" "+s),u(t,n)};const u=(t,e)=>{const s=t=>t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),n=new RegExp("[^\0-]"),i=t.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t);if(n.test(t))return i.some(t=>e.toLowerCase().indexOf(t)>-1);{const n=t.endsWith(" ");return new RegExp(i.map((t,e)=>i.length!==e+1||n?`(?=.*\\b${s(t)}\\b)`:`(?=.*\\b${s(t)})`).join("")+".+","gi").test(e)}};var c={name:"SearchBox",data:()=>({query:"",focused:!1,focusIndex:0,placeholder:void 0}),computed:{showSuggestions(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions(){const t=this.query.trim().toLowerCase();if(!t)return;const{pages:e}=this.$site,s=this.$site.themeConfig.searchMaxSuggestions||5,n=this.$localePath,i=[];for(let r=0;r=s);r++){const a=e[r];if(this.getPageLocalePath(a)===n&&this.isSearchable(a))if(l(t,a))i.push(a);else if(a.headers)for(let e=0;e=s);e++){const s=a.headers[e];s.title&&l(t,a,s.title)&&i.push(Object.assign({},a,{path:a.path+"#"+s.slug,header:s}))}}return i},alignRight(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath(t){for(const e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable(t){let e=null;return null===e||(e=Array.isArray(e)?e:new Array(e),e.filter(e=>t.path.match(e)).length>0)},onHotkey(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown(){this.showSuggestions&&(this.focusIndex "+t._s(s.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),p=(s(334),Object(i.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[e("svg",{staticClass:"icon",attrs:{viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img"}},[e("g",{staticClass:"hamburger",attrs:{fill:"currentColor"}},[e("path",{attrs:{d:"M33.75 11.6699H6.25C5.55964 11.6699 5 12.2296 5 12.9199C5 13.6103 5.55964 14.1699 6.25 14.1699H33.75C34.4404 14.1699 35 13.6103 35 12.9199C35 12.2296 34.4404 11.6699 33.75 11.6699Z"}}),t._v(" "),e("path",{attrs:{d:"M28.75 18.752H6.25C5.55964 18.752 5 19.3116 5 20.002C5 20.6923 5.55964 21.252 6.25 21.252H28.75C29.4404 21.252 30 20.6923 30 20.002C30 19.3116 29.4404 18.752 28.75 18.752Z"}}),t._v(" "),e("path",{attrs:{d:"M33.75 25.8301H6.25C5.55964 25.8301 5 26.3897 5 27.0801C5 27.7704 5.55964 28.3301 6.25 28.3301H33.75C34.4404 28.3301 35 27.7704 35 27.0801C35 26.3897 34.4404 25.8301 33.75 25.8301Z"}})]),t._v(" "),e("g",{staticClass:"close",attrs:{stroke:"currentColor"}},[e("path",{attrs:{d:"M10 10L30 30","stroke-width":"2","stroke-linecap":"round"}}),t._v(" "),e("path",{attrs:{d:"M30 10L10 30","stroke-width":"2","stroke-linecap":"round"}})])])])}),[],!1,null,null,null).exports),d=s(280),f=s(327),g=s(111),m=s.n(g),b={name:"DropdownLink",components:{NavLink:d.a,DropdownTransition:f.a},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>m()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},v=(s(336),Object(i.a)(b,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(s,n){return e("li",{key:s.link||n,staticClass:"dropdown-item"},["links"===s.type?e("h4",[t._v("\n "+t._s(s.text)+"\n ")]):t._e(),t._v(" "),"links"===s.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(s.items,(function(n){return e("li",{key:n.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,s.items)&&t.isLastItemOfArray(s,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:s},on:{focusout:function(e){t.isLastItemOfArray(s,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports),C=s(252),k={name:"NavLinks",components:{NavLink:d.a,DropdownLink:v},computed:{userNav(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav(){const{locales:t}=this.$site;if(t&&Object.keys(t).length>1){const e=this.$page.path,s=this.$router.options.routes,n=this.$site.themeConfig.locales||{},i={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(t).map(i=>{const r=t[i],a=n[i]&&n[i].label||r.lang;let o;return r.lang===this.$lang?o=e:(o=e.replace(this.$localeConfig.path,i),s.some(t=>t.path===o)||(o=i)),{text:a,link:o}})};return[...this.userNav,i]}return this.userNav},userLinks(){return(this.nav||[]).map(t=>Object.assign(Object(C.j)(t),{items:(t.items||[]).map(C.j)}))},repoLink(){const{repo:t}=this.$site.themeConfig;return t?/^https?:/.test(t)?t:"https://github.com/"+t:null},repoLabel(){if(!this.repoLink)return;if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;const t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"];for(let s=0;s({linksWrapMaxWidth:null}),computed:{algolia(){return this.$themeLocaleConfig.algolia||this.$site.themeConfig.algolia||{}},isAlgoliaSearch(){return this.algolia&&this.algolia.apiKey&&this.algolia.indexName}},mounted(){const t=parseInt(y(this.$el,"paddingLeft"))+parseInt(y(this.$el,"paddingRight")),e=()=>{document.documentElement.clientWidth<719?this.linksWrapMaxWidth=null:this.linksWrapMaxWidth=this.$el.offsetWidth-t-(this.$refs.siteName&&this.$refs.siteName.offsetWidth||0)};e(),window.addEventListener("resize",e,!1)},methods:{toggleColorMode(t){t.preventDefault();const e=(document.documentElement.getAttribute(w.THEME_ATTR)||w.COLOR_MODES[0])===w.COLOR_MODES[0]?w.COLOR_MODES[1]:w.COLOR_MODES[0];Object(w.setColorMode)(e)}}},L=(s(338),Object(i.a)(x,(function(){var t=this,e=t._self._c;return e("header",{staticClass:"navbar"},[e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("RouterLink",{staticClass:"home-link",attrs:{to:t.$localePath}},[t.$site.themeConfig.logo?e("svg",{staticClass:"logo",attrs:{role:"img",alt:t.$siteTitle}},[e("use",{staticClass:"small",attrs:{href:t.$withBase(t.$site.themeConfig.logo)+"#small"}}),t._v(" "),e("use",{staticClass:"large",attrs:{href:t.$withBase(t.$site.themeConfig.logo)+"#large"}})]):t._e()]),t._v(" "),e("div",{staticClass:"links",style:t.linksWrapMaxWidth?{"max-width":t.linksWrapMaxWidth+"px"}:{}},[e("NavLinks",{staticClass:"can-hide"}),t._v(" "),t.isAlgoliaSearch?e("AlgoliaSearchBox",{attrs:{options:t.algolia}}):!1!==t.$site.themeConfig.search&&!1!==t.$page.frontmatter.search?e("SearchBox"):t._e(),t._v(" "),e("button",{staticClass:"theme-switch",attrs:{type:"button"},on:{click:function(e){return t.toggleColorMode(e)}}},[e("svg",{attrs:{viewBox:"0 0 30 31",fill:"none",xmlns:"http://www.w3.org/2000/svg"}},[e("g",{staticClass:"theme-switch-dark"},[e("path",{attrs:{d:"M15 20.4219C12.5187 20.4219 10.5 18.4032 10.5 15.9219C10.5 13.4406 12.5187 11.4219 15 11.4219C17.4813 11.4219 19.5 13.4406 19.5 15.9219C19.5 18.4032 17.4813 20.4219 15 20.4219Z",fill:"currentColor"}}),t._v(" "),e("path",{attrs:{d:"M19.4541 20.3769L21.3644 22.2862M15 24.9219V22.2219V24.9219ZM15 9.62187V6.92188V9.62187ZM6 15.9219H8.7H6ZM21.3 15.9219H24H21.3ZM8.6361 22.2862L10.5454 20.3769L8.6361 22.2862ZM19.4541 11.4678L21.3644 9.55797L19.4541 11.4678ZM8.6361 9.55797L10.5454 11.4678L8.6361 9.55797Z",stroke:"currentColor","stroke-width":"1","stroke-linecap":"round"}})]),t._v(" "),e("g",{staticClass:"theme-switch-light",attrs:{fill:"currentColor"}},[e("path",{attrs:{d:"M10.1539 8.75585C10.018 8.75585 9.88774 8.70189 9.79168 8.60583C9.69563 8.50977 9.64166 8.37949 9.64166 8.24365V6.19482C9.64166 6.05898 9.69563 5.9287 9.79168 5.83264C9.88774 5.73658 10.018 5.68262 10.1539 5.68262C10.2897 5.68262 10.42 5.73658 10.5161 5.83264C10.6121 5.9287 10.6661 6.05898 10.6661 6.19482V8.24365C10.6661 8.37949 10.6121 8.50977 10.5161 8.60583C10.42 8.70189 10.2897 8.75585 10.1539 8.75585Z"}}),t._v(" "),e("path",{attrs:{d:"M11.1783 7.73144H9.12945C8.9936 7.73144 8.86332 7.67748 8.76726 7.58142C8.6712 7.48536 8.61724 7.35508 8.61724 7.21924C8.61724 7.08339 8.6712 6.95311 8.76726 6.85705C8.86332 6.761 8.9936 6.70703 9.12945 6.70703H11.1783C11.3141 6.70703 11.4444 6.761 11.5405 6.85705C11.6365 6.95311 11.6905 7.08339 11.6905 7.21924C11.6905 7.35508 11.6365 7.48536 11.5405 7.58142C11.4444 7.67748 11.3141 7.73144 11.1783 7.73144ZM6.05621 13.8779C5.92037 13.8779 5.79009 13.8239 5.69403 13.7279C5.59797 13.6318 5.54401 13.5015 5.54401 13.3657V12.3413C5.54401 12.2054 5.59797 12.0752 5.69403 11.9791C5.79009 11.8831 5.92037 11.8291 6.05621 11.8291C6.19206 11.8291 6.32234 11.8831 6.4184 11.9791C6.51445 12.0752 6.56842 12.2054 6.56842 12.3413V13.3657C6.56842 13.5015 6.51445 13.6318 6.4184 13.7279C6.32234 13.8239 6.19206 13.8779 6.05621 13.8779Z"}}),t._v(" "),e("path",{attrs:{d:"M6.56842 13.366H5.544C5.40816 13.366 5.27788 13.312 5.18182 13.216C5.08576 13.1199 5.0318 12.9896 5.0318 12.8538C5.0318 12.7179 5.08576 12.5877 5.18182 12.4916C5.27788 12.3955 5.40816 12.3416 5.544 12.3416H6.56842C6.70426 12.3416 6.83454 12.3955 6.9306 12.4916C7.02666 12.5877 7.08062 12.7179 7.08062 12.8538C7.08062 12.9896 7.02666 13.1199 6.9306 13.216C6.83454 13.312 6.70426 13.366 6.56842 13.366ZM16.8125 23.6101C12.8583 23.6101 9.64165 20.3934 9.64165 16.4392C9.64165 12.8983 12.2851 9.85021 15.7907 9.34876L16.4658 9.25195L16.37 9.92755C16.326 10.218 16.3027 10.5112 16.3003 10.805C16.3003 14.1942 19.0575 16.9514 22.4468 16.9514C22.708 16.9514 22.9872 16.9294 23.3247 16.8813L23.9998 16.7855L23.9035 17.4606C23.401 20.9666 20.3524 23.6101 16.8125 23.6101Z"}})])])])],1),t._v(" "),e("SidebarButton",{on:{"toggle-sidebar":function(e){return t.$emit("toggle-sidebar")}}})],1)])])}),[],!1,null,null,null).exports),$={name:"Sidebar",components:{SidebarLinks:s(326).default,NavLinks:_},props:["items"]},O=(s(341),Object(i.a)($,(function(){var t=this._self._c;return t("aside",{staticClass:"sidebar"},[t("NavLinks"),this._v(" "),this._t("top"),this._v(" "),t("SidebarLinks",{attrs:{depth:0,items:this.items}}),this._v(" "),this._t("bottom")],2)}),[],!1,null,null,null).exports),S={name:"Footer",components:{NavLink:d.a},computed:{links(){return this.$site.themeConfig.footer.links},copyright(){return this.$site.themeConfig.footer.copyright}}},j=(s(342),{name:"Layout",components:{Sidebar:O,Navbar:L,Footer:Object(i.a)(S,(function(){var t=this,e=t._self._c;return e("footer",{staticClass:"footer"},[e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("div",{staticClass:"inner"},[e("div",{staticClass:"footer-content"},t._l(t.links,(function(s){return e("div",{key:s.title,staticClass:"footer-block"},[e("h4",[t._v(t._s(s.title))]),t._v(" "),t._l(s.children,(function(t){return e("div",{key:t.link},[e("NavLink",{attrs:{item:t}})],1)}))],2)})),0),t._v(" "),t.copyright?e("p",{staticClass:"copyright"},[t._v(t._s(t.copyright))]):t._e()])])])])}),[],!1,null,null,null).exports},data:()=>({isSidebarOpen:!1}),computed:{shouldShowNavbar(){const{themeConfig:t}=this.$site,{frontmatter:e}=this.$page;return!1!==e.navbar&&!1!==t.navbar&&(this.$title||t.logo||t.repo||t.nav||this.$themeLocaleConfig.nav)},shouldShowSidebar(){const{frontmatter:t}=this.$page;return!t.home&&!1!==t.sidebar&&this.sidebarItems.length},sidebarItems(){return Object(C.l)(this.$page,this.$page.regularPath,this.$site,this.$localePath)},pageClasses(){const t=this.$page.frontmatter.pageClass;return[{"no-navbar":!this.shouldShowNavbar,"sidebar-open":this.isSidebarOpen,"no-sidebar":!this.shouldShowSidebar},t]}},mounted(){this.$router.afterEach(()=>{this.isSidebarOpen=!1})},methods:{toggleSidebar(t){this.isSidebarOpen="boolean"==typeof t?t:!this.isSidebarOpen,this.$emit("toggle-sidebar",this.isSidebarOpen)},onTouchStart(t){this.touchStart={x:t.changedTouches[0].clientX,y:t.changedTouches[0].clientY}},onTouchEnd(t){const e=t.changedTouches[0].clientX-this.touchStart.x,s=t.changedTouches[0].clientY-this.touchStart.y;Math.abs(e)>Math.abs(s)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),I=(s(343),Object(i.a)(j,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?e("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),e("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t._t("default")],2)]),t._v(" "),e("Footer")],1)}),[],!1,null,"b812d5fc",null));e.a=I.exports},280:function(t,e,s){"use strict";var n=s(252),i={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(n.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(n.g)(this.link)||Object(n.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(n.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(n.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},r=s(7),a=Object(r.a)(i,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.a=a.exports},288:function(t,e,s){"use strict";var n=TypeError;t.exports=function(t,e){if(t2&&(r.style={"padding-left":i+"rem"}),t("RouterLink",r,s)}function u(t,e,s,n,r,a=1){return!e||a>r?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const o=Object(i.e)(n,s+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[l(t,s+"#"+e.slug,e.title,o,e.level-1),u(t,e.children,s,n,r,a+1)])}))}var c={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:s,$route:n,$themeConfig:r,$themeLocaleConfig:a},props:{item:o,sidebarDepth:c}}){const h=Object(i.e)(n,o.path),p="auto"===o.type?h||o.children.some(t=>Object(i.e)(n,o.basePath+"#"+t.slug)):h,d="external"===o.type?function(t,e,s){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[s,t("OutboundLink")])}(t,o.path,o.title||o.path):l(t,o.path,o.title||o.path,p),f=[e.frontmatter.sidebarDepth,c,a.sidebarDepth,r.sidebarDepth,1].find(t=>void 0!==t),g=a.displayAllHeaders||r.displayAllHeaders;if("auto"===o.type)return[d,u(t,o.children,o.basePath,n,f)];if((p||g)&&o.headers&&!i.d.test(o.path)){return[d,u(t,Object(i.c)(o.headers),o.path,n,f)]}return d}};s(340);function h(t,e){if("group"===e.type){const s=e.path&&Object(i.e)(t,e.path),n=e.children.some(e=>"group"===e.type?h(t,e):"page"===e.type&&Object(i.e)(t,e.path));return s||n}return!1}var p={name:"SidebarLinks",components:{SidebarGroup:o,SidebarLink:Object(a.a)(c,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route(){this.refreshIndex()}},created(){this.refreshIndex()},methods:{refreshIndex(){const t=function(t,e){for(let s=0;s-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(i.e)(this.$route,t.regularPath)}}},d=Object(a.a)(p,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(s,n){return e("li",{key:n},["group"===s.type?e("SidebarGroup",{attrs:{item:s,open:n===t.openGroupIndex,collapsable:s.collapsable||s.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(n)}}}):e("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:s}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=d.exports},327:function(t,e,s){"use strict";var n={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(s(335),s(7)),r=Object(i.a)(n,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=r.exports},328:function(t,e,s){"use strict";var n=s(106),i=s(2),r=s(107),a=s(288),o=URLSearchParams,l=o.prototype,u=i(l.append),c=i(l.delete),h=i(l.forEach),p=i([].push),d=new o("a=1&a=2&b=3");d.delete("a",1),d.delete("b",void 0),d+""!="a=2"&&n(l,"delete",(function(t){var e=arguments.length,s=e<2?void 0:arguments[1];if(e&&void 0===s)return c(this,t);var n=[];h(this,(function(t,e){p(n,{key:e,value:t})})),a(e,1);for(var i,o=r(t),l=r(s),d=0,f=0,g=!1,m=n.length;dfunction t(e,s,n,i=1){if("string"==typeof e)return d(s,e,n);if(Array.isArray(e))return Object.assign(d(s,e[0],n),{title:e[1]});{const r=e.children||[];return 0===r.length&&e.path?Object.assign(d(s,e.path,n),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:r.map(e=>t(e,s,n,i+1)),collapsable:!1!==e.collapsable}}}(t,i,s)):[]}return[]}function g(t){const e=m(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function m(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function b(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},259:function(t,e,s){"use strict";s(328),s(329),s(330),s(46);var n={name:"AlgoliaSearchBox",props:["options"],data:()=>({placeholder:void 0}),watch:{$lang(t){this.update(this.options,t)},options(t){this.update(t,this.$lang)}},mounted(){this.initialize(this.options,this.$lang),this.placeholder=this.$site.themeConfig.searchPlaceholder||""},methods:{initialize(t,e){Promise.all([Promise.all([s.e(0),s.e(3)]).then(s.t.bind(null,373,7)),Promise.all([s.e(0),s.e(3)]).then(s.t.bind(null,374,7))]).then(([s])=>{s=s.default;const{algoliaOptions:n={}}=t;s(Object.assign({},t,{inputSelector:"#algolia-search-input",algoliaOptions:{...n,facetFilters:["lang:"+e].concat(n.facetFilters||[])},handleSelected:(t,e,s)=>{const{pathname:n,hash:i}=new URL(s.url),r=n.replace(this.$site.base,"/"),a=decodeURIComponent(i);this.$router.push(`${r}${a}`)}}))})},update(t,e){this.$el.innerHTML='',this.initialize(t,e)}}},i=(s(332),s(7)),r=Object(i.a)(n,(function(){var t=this._self._c;return t("form",{staticClass:"algolia-search-wrapper search-box",attrs:{id:"search-form",role:"search"}},[t("input",{staticClass:"search-query",attrs:{id:"algolia-search-input",placeholder:this.placeholder}})])}),[],!1,null,null,null).exports,a=s(110),o=s.n(a),l=(t,e,s=null)=>{let n=o()(e,"title","");return o()(e,"frontmatter.tags")&&(n+=" "+e.frontmatter.tags.join(" ")),s&&(n+=" "+s),u(t,n)};const u=(t,e)=>{const s=t=>t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),n=new RegExp("[^\0-]"),i=t.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t);if(n.test(t))return i.some(t=>e.toLowerCase().indexOf(t)>-1);{const n=t.endsWith(" ");return new RegExp(i.map((t,e)=>i.length!==e+1||n?`(?=.*\\b${s(t)}\\b)`:`(?=.*\\b${s(t)})`).join("")+".+","gi").test(e)}};var c={name:"SearchBox",data:()=>({query:"",focused:!1,focusIndex:0,placeholder:void 0}),computed:{showSuggestions(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions(){const t=this.query.trim().toLowerCase();if(!t)return;const{pages:e}=this.$site,s=this.$site.themeConfig.searchMaxSuggestions||5,n=this.$localePath,i=[];for(let r=0;r=s);r++){const a=e[r];if(this.getPageLocalePath(a)===n&&this.isSearchable(a))if(l(t,a))i.push(a);else if(a.headers)for(let e=0;e=s);e++){const s=a.headers[e];s.title&&l(t,a,s.title)&&i.push(Object.assign({},a,{path:a.path+"#"+s.slug,header:s}))}}return i},alignRight(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath(t){for(const e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable(t){let e=null;return null===e||(e=Array.isArray(e)?e:new Array(e),e.filter(e=>t.path.match(e)).length>0)},onHotkey(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown(){this.showSuggestions&&(this.focusIndex "+t._s(s.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),p=(s(334),Object(i.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[e("svg",{staticClass:"icon",attrs:{viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img"}},[e("g",{staticClass:"hamburger",attrs:{fill:"currentColor"}},[e("path",{attrs:{d:"M33.75 11.6699H6.25C5.55964 11.6699 5 12.2296 5 12.9199C5 13.6103 5.55964 14.1699 6.25 14.1699H33.75C34.4404 14.1699 35 13.6103 35 12.9199C35 12.2296 34.4404 11.6699 33.75 11.6699Z"}}),t._v(" "),e("path",{attrs:{d:"M28.75 18.752H6.25C5.55964 18.752 5 19.3116 5 20.002C5 20.6923 5.55964 21.252 6.25 21.252H28.75C29.4404 21.252 30 20.6923 30 20.002C30 19.3116 29.4404 18.752 28.75 18.752Z"}}),t._v(" "),e("path",{attrs:{d:"M33.75 25.8301H6.25C5.55964 25.8301 5 26.3897 5 27.0801C5 27.7704 5.55964 28.3301 6.25 28.3301H33.75C34.4404 28.3301 35 27.7704 35 27.0801C35 26.3897 34.4404 25.8301 33.75 25.8301Z"}})]),t._v(" "),e("g",{staticClass:"close",attrs:{stroke:"currentColor"}},[e("path",{attrs:{d:"M10 10L30 30","stroke-width":"2","stroke-linecap":"round"}}),t._v(" "),e("path",{attrs:{d:"M30 10L10 30","stroke-width":"2","stroke-linecap":"round"}})])])])}),[],!1,null,null,null).exports),d=s(280),f=s(327),g=s(111),m=s.n(g),b={name:"DropdownLink",components:{NavLink:d.a,DropdownTransition:f.a},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>m()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},v=(s(336),Object(i.a)(b,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(s,n){return e("li",{key:s.link||n,staticClass:"dropdown-item"},["links"===s.type?e("h4",[t._v("\n "+t._s(s.text)+"\n ")]):t._e(),t._v(" "),"links"===s.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(s.items,(function(n){return e("li",{key:n.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,s.items)&&t.isLastItemOfArray(s,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:s},on:{focusout:function(e){t.isLastItemOfArray(s,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports),C=s(252),k={name:"NavLinks",components:{NavLink:d.a,DropdownLink:v},computed:{userNav(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav(){const{locales:t}=this.$site;if(t&&Object.keys(t).length>1){const e=this.$page.path,s=this.$router.options.routes,n=this.$site.themeConfig.locales||{},i={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(t).map(i=>{const r=t[i],a=n[i]&&n[i].label||r.lang;let o;return r.lang===this.$lang?o=e:(o=e.replace(this.$localeConfig.path,i),s.some(t=>t.path===o)||(o=i)),{text:a,link:o}})};return[...this.userNav,i]}return this.userNav},userLinks(){return(this.nav||[]).map(t=>Object.assign(Object(C.j)(t),{items:(t.items||[]).map(C.j)}))},repoLink(){const{repo:t}=this.$site.themeConfig;return t?/^https?:/.test(t)?t:"https://github.com/"+t:null},repoLabel(){if(!this.repoLink)return;if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;const t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"];for(let s=0;s({linksWrapMaxWidth:null}),computed:{algolia(){return this.$themeLocaleConfig.algolia||this.$site.themeConfig.algolia||{}},isAlgoliaSearch(){return this.algolia&&this.algolia.apiKey&&this.algolia.indexName}},mounted(){const t=parseInt(y(this.$el,"paddingLeft"))+parseInt(y(this.$el,"paddingRight")),e=()=>{document.documentElement.clientWidth<719?this.linksWrapMaxWidth=null:this.linksWrapMaxWidth=this.$el.offsetWidth-t-(this.$refs.siteName&&this.$refs.siteName.offsetWidth||0)};e(),window.addEventListener("resize",e,!1)},methods:{toggleColorMode(t){t.preventDefault();const e=(document.documentElement.getAttribute(w.THEME_ATTR)||w.COLOR_MODES[0])===w.COLOR_MODES[0]?w.COLOR_MODES[1]:w.COLOR_MODES[0];Object(w.setColorMode)(e)}}},L=(s(338),Object(i.a)(x,(function(){var t=this,e=t._self._c;return e("header",{staticClass:"navbar"},[e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("RouterLink",{staticClass:"home-link",attrs:{to:t.$localePath}},[t.$site.themeConfig.logo?e("svg",{staticClass:"logo",attrs:{role:"img",alt:t.$siteTitle}},[e("use",{staticClass:"small",attrs:{href:t.$withBase(t.$site.themeConfig.logo)+"#small"}}),t._v(" "),e("use",{staticClass:"large",attrs:{href:t.$withBase(t.$site.themeConfig.logo)+"#large"}})]):t._e()]),t._v(" "),e("div",{staticClass:"links",style:t.linksWrapMaxWidth?{"max-width":t.linksWrapMaxWidth+"px"}:{}},[e("NavLinks",{staticClass:"can-hide"}),t._v(" "),t.isAlgoliaSearch?e("AlgoliaSearchBox",{attrs:{options:t.algolia}}):!1!==t.$site.themeConfig.search&&!1!==t.$page.frontmatter.search?e("SearchBox"):t._e(),t._v(" "),e("button",{staticClass:"theme-switch",attrs:{type:"button"},on:{click:function(e){return t.toggleColorMode(e)}}},[e("svg",{attrs:{viewBox:"0 0 30 31",fill:"none",xmlns:"http://www.w3.org/2000/svg"}},[e("g",{staticClass:"theme-switch-dark"},[e("path",{attrs:{d:"M15 20.4219C12.5187 20.4219 10.5 18.4032 10.5 15.9219C10.5 13.4406 12.5187 11.4219 15 11.4219C17.4813 11.4219 19.5 13.4406 19.5 15.9219C19.5 18.4032 17.4813 20.4219 15 20.4219Z",fill:"currentColor"}}),t._v(" "),e("path",{attrs:{d:"M19.4541 20.3769L21.3644 22.2862M15 24.9219V22.2219V24.9219ZM15 9.62187V6.92188V9.62187ZM6 15.9219H8.7H6ZM21.3 15.9219H24H21.3ZM8.6361 22.2862L10.5454 20.3769L8.6361 22.2862ZM19.4541 11.4678L21.3644 9.55797L19.4541 11.4678ZM8.6361 9.55797L10.5454 11.4678L8.6361 9.55797Z",stroke:"currentColor","stroke-width":"1","stroke-linecap":"round"}})]),t._v(" "),e("g",{staticClass:"theme-switch-light",attrs:{fill:"currentColor"}},[e("path",{attrs:{d:"M10.1539 8.75585C10.018 8.75585 9.88774 8.70189 9.79168 8.60583C9.69563 8.50977 9.64166 8.37949 9.64166 8.24365V6.19482C9.64166 6.05898 9.69563 5.9287 9.79168 5.83264C9.88774 5.73658 10.018 5.68262 10.1539 5.68262C10.2897 5.68262 10.42 5.73658 10.5161 5.83264C10.6121 5.9287 10.6661 6.05898 10.6661 6.19482V8.24365C10.6661 8.37949 10.6121 8.50977 10.5161 8.60583C10.42 8.70189 10.2897 8.75585 10.1539 8.75585Z"}}),t._v(" "),e("path",{attrs:{d:"M11.1783 7.73144H9.12945C8.9936 7.73144 8.86332 7.67748 8.76726 7.58142C8.6712 7.48536 8.61724 7.35508 8.61724 7.21924C8.61724 7.08339 8.6712 6.95311 8.76726 6.85705C8.86332 6.761 8.9936 6.70703 9.12945 6.70703H11.1783C11.3141 6.70703 11.4444 6.761 11.5405 6.85705C11.6365 6.95311 11.6905 7.08339 11.6905 7.21924C11.6905 7.35508 11.6365 7.48536 11.5405 7.58142C11.4444 7.67748 11.3141 7.73144 11.1783 7.73144ZM6.05621 13.8779C5.92037 13.8779 5.79009 13.8239 5.69403 13.7279C5.59797 13.6318 5.54401 13.5015 5.54401 13.3657V12.3413C5.54401 12.2054 5.59797 12.0752 5.69403 11.9791C5.79009 11.8831 5.92037 11.8291 6.05621 11.8291C6.19206 11.8291 6.32234 11.8831 6.4184 11.9791C6.51445 12.0752 6.56842 12.2054 6.56842 12.3413V13.3657C6.56842 13.5015 6.51445 13.6318 6.4184 13.7279C6.32234 13.8239 6.19206 13.8779 6.05621 13.8779Z"}}),t._v(" "),e("path",{attrs:{d:"M6.56842 13.366H5.544C5.40816 13.366 5.27788 13.312 5.18182 13.216C5.08576 13.1199 5.0318 12.9896 5.0318 12.8538C5.0318 12.7179 5.08576 12.5877 5.18182 12.4916C5.27788 12.3955 5.40816 12.3416 5.544 12.3416H6.56842C6.70426 12.3416 6.83454 12.3955 6.9306 12.4916C7.02666 12.5877 7.08062 12.7179 7.08062 12.8538C7.08062 12.9896 7.02666 13.1199 6.9306 13.216C6.83454 13.312 6.70426 13.366 6.56842 13.366ZM16.8125 23.6101C12.8583 23.6101 9.64165 20.3934 9.64165 16.4392C9.64165 12.8983 12.2851 9.85021 15.7907 9.34876L16.4658 9.25195L16.37 9.92755C16.326 10.218 16.3027 10.5112 16.3003 10.805C16.3003 14.1942 19.0575 16.9514 22.4468 16.9514C22.708 16.9514 22.9872 16.9294 23.3247 16.8813L23.9998 16.7855L23.9035 17.4606C23.401 20.9666 20.3524 23.6101 16.8125 23.6101Z"}})])])])],1),t._v(" "),e("SidebarButton",{on:{"toggle-sidebar":function(e){return t.$emit("toggle-sidebar")}}})],1)])])}),[],!1,null,null,null).exports),$={name:"Sidebar",components:{SidebarLinks:s(326).default,NavLinks:_},props:["items"]},O=(s(341),Object(i.a)($,(function(){var t=this._self._c;return t("aside",{staticClass:"sidebar"},[t("NavLinks"),this._v(" "),this._t("top"),this._v(" "),t("SidebarLinks",{attrs:{depth:0,items:this.items}}),this._v(" "),this._t("bottom")],2)}),[],!1,null,null,null).exports),S={name:"Footer",components:{NavLink:d.a},computed:{links(){return this.$site.themeConfig.footer.links},copyright(){return this.$site.themeConfig.footer.copyright}}},j=(s(342),{name:"Layout",components:{Sidebar:O,Navbar:L,Footer:Object(i.a)(S,(function(){var t=this,e=t._self._c;return e("footer",{staticClass:"footer"},[e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("div",{staticClass:"inner"},[e("div",{staticClass:"footer-content"},t._l(t.links,(function(s){return e("div",{key:s.title,staticClass:"footer-block"},[e("h4",[t._v(t._s(s.title))]),t._v(" "),t._l(s.children,(function(t){return e("div",{key:t.link},[e("NavLink",{attrs:{item:t}})],1)}))],2)})),0),t._v(" "),t.copyright?e("p",{staticClass:"copyright"},[t._v(t._s(t.copyright))]):t._e()])])])])}),[],!1,null,null,null).exports},data:()=>({isSidebarOpen:!1}),computed:{shouldShowNavbar(){const{themeConfig:t}=this.$site,{frontmatter:e}=this.$page;return!1!==e.navbar&&!1!==t.navbar&&(this.$title||t.logo||t.repo||t.nav||this.$themeLocaleConfig.nav)},shouldShowSidebar(){const{frontmatter:t}=this.$page;return!t.home&&!1!==t.sidebar&&this.sidebarItems.length},sidebarItems(){return Object(C.l)(this.$page,this.$page.regularPath,this.$site,this.$localePath)},pageClasses(){const t=this.$page.frontmatter.pageClass;return[{"no-navbar":!this.shouldShowNavbar,"sidebar-open":this.isSidebarOpen,"no-sidebar":!this.shouldShowSidebar},t]}},mounted(){this.$router.afterEach(()=>{this.isSidebarOpen=!1})},methods:{toggleSidebar(t){this.isSidebarOpen="boolean"==typeof t?t:!this.isSidebarOpen,this.$emit("toggle-sidebar",this.isSidebarOpen)},onTouchStart(t){this.touchStart={x:t.changedTouches[0].clientX,y:t.changedTouches[0].clientY}},onTouchEnd(t){const e=t.changedTouches[0].clientX-this.touchStart.x,s=t.changedTouches[0].clientY-this.touchStart.y;Math.abs(e)>Math.abs(s)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),I=(s(343),Object(i.a)(j,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?e("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),e("div",{staticClass:"wrap"},[e("div",{staticClass:"wrap-border"},[e("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),e("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t._t("default")],2)]),t._v(" "),e("Footer")],1)}),[],!1,null,"b812d5fc",null));e.a=I.exports},280:function(t,e,s){"use strict";var n=s(252),i={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(n.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(n.g)(this.link)||Object(n.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(n.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(n.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},r=s(7),a=Object(r.a)(i,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.a=a.exports},288:function(t,e,s){"use strict";var n=TypeError;t.exports=function(t,e){if(t2&&(r.style={"padding-left":i+"rem"}),t("RouterLink",r,s)}function u(t,e,s,n,r,a=1){return!e||a>r?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const o=Object(i.e)(n,s+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[l(t,s+"#"+e.slug,e.title,o,e.level-1),u(t,e.children,s,n,r,a+1)])}))}var c={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:s,$route:n,$themeConfig:r,$themeLocaleConfig:a},props:{item:o,sidebarDepth:c}}){const h=Object(i.e)(n,o.path),p="auto"===o.type?h||o.children.some(t=>Object(i.e)(n,o.basePath+"#"+t.slug)):h,d="external"===o.type?function(t,e,s){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[s,t("OutboundLink")])}(t,o.path,o.title||o.path):l(t,o.path,o.title||o.path,p),f=[e.frontmatter.sidebarDepth,c,a.sidebarDepth,r.sidebarDepth,1].find(t=>void 0!==t),g=a.displayAllHeaders||r.displayAllHeaders;if("auto"===o.type)return[d,u(t,o.children,o.basePath,n,f)];if((p||g)&&o.headers&&!i.d.test(o.path)){return[d,u(t,Object(i.c)(o.headers),o.path,n,f)]}return d}};s(340);function h(t,e){if("group"===e.type){const s=e.path&&Object(i.e)(t,e.path),n=e.children.some(e=>"group"===e.type?h(t,e):"page"===e.type&&Object(i.e)(t,e.path));return s||n}return!1}var p={name:"SidebarLinks",components:{SidebarGroup:o,SidebarLink:Object(a.a)(c,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route(){this.refreshIndex()}},created(){this.refreshIndex()},methods:{refreshIndex(){const t=function(t,e){for(let s=0;s-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(i.e)(this.$route,t.regularPath)}}},d=Object(a.a)(p,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(s,n){return e("li",{key:n},["group"===s.type?e("SidebarGroup",{attrs:{item:s,open:n===t.openGroupIndex,collapsable:s.collapsable||s.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(n)}}}):e("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:s}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=d.exports},327:function(t,e,s){"use strict";var n={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(s(335),s(7)),r=Object(i.a)(n,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=r.exports},328:function(t,e,s){"use strict";var n=s(106),i=s(2),r=s(107),a=s(288),o=URLSearchParams,l=o.prototype,u=i(l.append),c=i(l.delete),h=i(l.forEach),p=i([].push),d=new o("a=1&a=2&b=3");d.delete("a",1),d.delete("b",void 0),d+""!="a=2"&&n(l,"delete",(function(t){var e=arguments.length,s=e<2?void 0:arguments[1];if(e&&void 0===s)return c(this,t);var n=[];h(this,(function(t,e){p(n,{key:e,value:t})})),a(e,1);for(var i,o=r(t),l=r(s),d=0,f=0,g=!1,m=n.length;dt,getPageLinkConfig:({frontmatter:t})=>t.next},PREV:{resolveLink:function(t,e){return v(t,e,-1)},getThemeLinkConfig:({prevLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.prev}};function h(t,{$themeConfig:e,$page:a,$route:n,$site:r,sidebarItems:o}){const{resolveLink:l,getThemeLinkConfig:c,getPageLinkConfig:u}=t,d=c(e),h=u(a),v=i()(h)?d:h;return!1===v?void 0:p()(v)?Object(s.k)(r.pages,v,n.path):l(a,o)}function v(t,e,a){const n=[];!function t(e,a){for(let n=0,i=e.length;nt,getPageLinkConfig:({frontmatter:t})=>t.next},PREV:{resolveLink:function(t,e){return v(t,e,-1)},getThemeLinkConfig:({prevLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.prev}};function h(t,{$themeConfig:e,$page:a,$route:n,$site:r,sidebarItems:o}){const{resolveLink:l,getThemeLinkConfig:c,getPageLinkConfig:u}=t,d=c(e),h=u(a),v=i()(h)?d:h;return!1===v?void 0:p()(v)?Object(s.k)(r.pages,v,n.path):l(a,o)}function v(t,e,a){const n=[];!function t(e,a){for(let n=0,i=e.length;n")])])])]),A._v(" "),I("div",{staticClass:"cross-promo"},[I("a",{attrs:{href:"https://bitcoindevkit.org/"}},[I("div",{staticClass:"cross-promo-inner"},[I("img",{attrs:{src:g(363)}}),A._v(" "),I("div",{staticClass:"divider"}),A._v(" "),I("p",{staticClass:"cross-promo-description"},[A._v("The on-chain companion to LDK")])])])])])}),[],!1,null,null,null);I.default=t.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{279:function(A,I){A.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAACCCAYAAACKAxD9AAAAAXNSR0IArs4c6QAAABplWElmTU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAATwHXnAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFdWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpBdHRyaWI9Imh0dHA6Ly9ucy5hdHRyaWJ1dGlvbi5jb20vYWRzLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjk2PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj45NjwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPGRjOmNyZWF0b3I+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpPkhhbGV5IEJlcmtvZTwvcmRmOmxpPgogICAgICAgICAgICA8L3JkZjpTZXE+CiAgICAgICAgIDwvZGM6Y3JlYXRvcj4KICAgICAgICAgPGRjOnRpdGxlPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5VbnRpdGxlZCBkZXNpZ24gLSAxPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPEF0dHJpYjpBZHM+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPEF0dHJpYjpUb3VjaFR5cGU+MjwvQXR0cmliOlRvdWNoVHlwZT4KICAgICAgICAgICAgICAgICAgPEF0dHJpYjpDcmVhdGVkPjIwMjQtMDQtMjM8L0F0dHJpYjpDcmVhdGVkPgogICAgICAgICAgICAgICAgICA8QXR0cmliOkV4dElkPmZmOGY1MDgxLTQ2YjEtNGVmYy1iZWUyLWY0NjIzZjA5Njc2NDwvQXR0cmliOkV4dElkPgogICAgICAgICAgICAgICAgICA8QXR0cmliOkZiSWQ+NTI1MjY1OTE0MTc5NTgwPC9BdHRyaWI6RmJJZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC9BdHRyaWI6QWRzPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkNhbnZhIChSZW5kZXJlcik8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CsmoN4cAAAwZSURBVHgB7Z1pqFZVF8e3ppbmUGZaaE45pEhJihma84QhpIRanzREUXP4YKSIKZSUoIGEA44oigNqmTaoDZZSlJbmPM9j5Zxlme7Wb73uw/G+5vtyn+e5zzmwFtx7ztnTWvu//nvttbdazpkYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhYAgYAoaAIWAIGAKGgCFgCBgChoAhkEQEiolRJZNomNlkCBgCeUCAiDA2D3pNZcIQgAg+YTaZOXlAoITovJ4HvaYyYQhYREiYQ/JlTvF8KTa9yULAiJAsf+TNGiNC3qBPlmIjQrL8kTdrjAh5gz5Zio0IyfJH3qwxIuQN+mQpNiIkyx95s8aIkDfok6XYiJAsf+TNGiNC3qBPlmIjQrL8kTdrjAh5gz5Zio0IyfJH3qwxIuQN+mQpNiIkyx95s8aIkDfok6U4b0QoWbKkK1aMvyBlkgQEipQIwfFVqlRx169fd957V7x4kZqQBMwTaUOReQES4PjatWu7s2fPurp167rq1au7mzdvWmRICDX46+xF8vPEE0+ontdff93Pnz9f3ytVqlQkuotqjinWk3sS3Hvvvf7xxx9Xh0+YMMFfvnzZDx48WL9lmzAiFNFC/B8kzQ0RZCtQBz/00EO+cuXK+j5v3jwvuYHftGmTfterV89IkAwSeP6BS9Yl5APVqlVzJ06c0PE3bNigieGOHTvcihUrtOzSpUt31V2qVCn3999/ax5RsCF1Emm0joTzr7/+cn/++WfUjDraUEf5tWvXtA7bKC/YluSVfKVEiRKudOnSms/QgfY3btxwv//+e9S/TJkyUZL7xx9/qI1UBpt4pw915EVBGIu+COPF6+h73333aR12XL169bZ6Tlm0Bw+E+fGOnmxJVlelTFbHC1uBGOm3b9/uP/roI//aa6/5H3/8UeuFJHfVKw6M6sOYjMWPgBLVhTKeAqaW32m7CXXx9rzHx/63NvF2dxpbyHPbOEHHI4884uPziOdDDz/8cDSHeJvQN66nYL0QNeqL7tAnk2dWIwKMh7WSFLo9e/a4Dh06uBkzZrjNmze7nj17OqLC559/LvY69+CDDzpYLpN0Fy5ccOfPn9fVR3/GYVXUqVNH686dOxfV0YfV++yzz7rHHnvMnT592glo7ueff3Zff/21E7D1VCLbjmvSpImOf+rUKffll1/qamfsWrVquf3796ut6IvrefLJJ9V+VvNvv/3mxGH6/Pjjj9VeTjydOnVyFSpU0HkwztatW/WdE1GjRo10ZTOndevWaTm/HnjgAffrr7+6Ll26aNmnn36qZRcvXtS5YlPjxo3d/fffr1ig75577lEbwSKcsIiw2EZ7Isju3bu1XTYiQ1YYJbPTcRo0aKDPoUOH+qNHj/qJEyf+X+OXL18+aheiBVFkxIgRWh5WU9WqVfX73Xff9Vu2bPFHjhzx27Zt89OmTYv6v/32237nzp3+m2++8T/99JOfPn261gkJfLNmzfxnn33m69ev7wVMLReH+SFDhuj7qFGjNIehH2N/9913/pNPPonGXrhwod+1a5eOjf7Ro0dHdR9++KHft2+fF0KqTXyDC7p4zpo1S+2i/8yZM7VMnK/P5cuXK170xfalS5dqecOGDfU5Z86caB7g8+233/ru3btrXbly5fQZfFDIZ3aSRU4GYcLvvfeeF+b6YcOGqYGy4vzUqVM9wLz//vv+gw8+0J8FCxb41atX+5EjR2o7iRL6FPbrE1DGjBmj74TSRx99VLcFWQlaxoR/+OEH36pVK/0O2xEgjR07NmpDO5JWns8995w6MQ7Wxo0bI8KhgzpskggWjQGJKD906JB/6qmnonLKJBLot0Q7z6mIMuyVfMi/8sor+o1+Wb3++eef9127dvUSMT0OrFmzptavX7/eL168WN+feeYZf/DgQd+xY0f9ZrwlS5YokXhnEXz11VdaV6NGjagNdYX9ycrWQIgiGdu7d68T5rqnn37akSgGOXDggCMxJAkjhBGOCfd9+/bVpOidd97RpiERCv1oS1hESOLYBhC2B8ImdbQhnCIhASRxDG3ZPo4fP676aHPlyhW1Y9KkSbrFEGYJ2zwRbETC+LwT8gn1/MjR140fP95JNHBCOEcIJ9FDsIWtA/nll1/UHiGAfgsxnURIJ1FOvwcNGuQkWroBAwboN32DCEEUT4kujv5gBTZCdNevXz/34osvOrYWJN4v9C/MM2MiAAJ7NsIe3aJFCyer3i1atEhBxVk4XrYKd/LkychGWQFOQroT1mtZxYoVdW+MGsgL+zkEQNCB81atWuXoS14QcozgCG1461fIznHcG2+84WTVuy+++EKJB3Fk1emY2Ee+AnmQQLyQq1CG7lD/5ptvqiMkCrnevXvrfGV7oJnai6OYE2MiYIGQhzC2bHWatzCmRAOt4xffLVu2dGvXrnVgQf+XX37ZyTanbehLnkCuJVFJ25J/9e/fX3MlyJ6JZHzFzDEGVr7wwgvq6Llz5+qkWFHh2MZRScKp2tm8eXNN1DgeAZjcMWiCF5JFGuEEhMmHlU2iRYIYwGPlkTjhoJUrV2r7cPyCPCSICJFIQnGkn0h15swZBbJt27auffv2jpXHKiwogRSUYy8ie7l76aWXXOvWrZ3s465du3ZaHn4RNbCZ6Pjqq686oiECHjgSZ7NYmAdED4LN33//vSai3bp1c7Nnz3Y9evQI1dpfchWtb9OmjZOtQpNaGrAgMpWMI0IItbLvO37uJn369HHjxo1zTGjgwIEacgEthOVAAEBDcCyromnTpnpu5kQQ2rKyOBUQ+tFLmJb9WftBGuohGmMRPcI9ADoI/xATEpF1ly1bNroX4BSD4JgQaUJU4jTEuLRn3myB9A+CQ5jbW2+9FYqiExRjUSdHaK2Ta3bXuXPnqB19w9YIJkTPgAeNqA9Rhu84ceOEoq4wkjERUIpzCMUAjgDc4cOH1RGTJ092HOUggCROTpJGR04gp4vbQNSOt35xpEJwMEcqog5jSrave/OtZrqi2CtxTFgVAN6rVy8NqRAHkDjGQRTk2LFjuqoJryGnWLZsmZP7Da1nP0ZYneESKlx8BcBxGPPlODx8+PDoGEhkCpGIrYD3ENGog6AIZCNSBP2UcckGuYJw/MauIGvWrImIQhlbXdAVbA5tC/ssdKYpCu/YN2TRnBI4GZDlcpQMx53wh0//1p/y+HGyYDvZQ++o9259GENI8l/9xKFRWTiNxMuEZFovRIzaxe3htFTQXslBbmsrdw7RN3VBD/3QFbebdyF11B6bOV0EndgTv1CK9w1tCvNkk0JJ1oTVC9O5WBES6GUMly/sazCXP37mEobVFQ99cQNCHRGGlcdeHcrIC8hJWO2ER8agjj2cSyWE6EDfENIpI9SSkLEayUvIMYJ+2rLqiQBBD3oZn3ahjG1G7jGibYTIwIoPmTvjEh1Z2aFPeHIxxVYUogtRjC2K0wVCPeORYyDgyGkmnEJIILE31NMfG5lz0KEdM/gVsU3GyPg9nOW5PEG4rAnjhvsBMTwqC3X2zBz7DDHMngHxkCf7l14aYRzhMPwJpJEge3hn6PiCizF7hgVnS2Lop0yZooq4xo3vaVk2vuBk7LvwUT17RMDJso96yQPUIXK0M8cU3jFFil3Wk0UhgwoJWEh0Qpk9k4tATohAth4uR5I7dbMsjkBOiBBXYO/pQOA/96npsNWszCECRoQcgpumoY0IafJWDm01IuQQ3DQNbURIk7dyaKsRIYfgpmloI0KavJVDW40IOQQ3TUMbEdLkrRzaakTIIbhpGtqIkCZv5dBWI0IOwU3T0EaENHkrh7YaEXIIbpqGNiKkyVs5tNWIkENw0zS0ESFN3sqhrfyTN/ufhOcQ4LQMbX9VLS2eyrGdEGFsjnXY8IaAIZAWBIgImf9XFtIyW7PTEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUPAEDAEDAFDwBAwBAwBQ8AQMAQMAUMgZQj8A1nFO753Z6pvAAAAAElFTkSuQmCC"},363:function(A,I,g){A.exports=g.p+"assets/img/bitkit.6eacba41.svg"},364:function(A,I,g){A.exports=g.p+"assets/img/mutiny.5939a956.svg"},365:function(A,I,g){A.exports=g.p+"assets/img/cashapp.db7a02f3.svg"},366:function(A,I,g){A.exports=g.p+"assets/img/bdk-logo.ea5ab41d.svg"},420:function(A,I,g){"use strict";g.r(I);var C=g(7),t=Object(C.a)({},(function(){var A=this,I=A._self._c;return I("ContentSlotsDistributor",{attrs:{"slot-key":A.$parent.slotKey}},[I("div",{staticClass:"case-studies"},[I("div",{staticClass:"case-studies-inner"},[I("div",{staticClass:"logo-wrapper"},[I("img",{attrs:{src:g(363)}}),A._v(" "),I("img",{attrs:{src:g(364)}}),A._v(" "),I("img",{attrs:{src:g(365)}}),A._v(" "),I("img",{attrs:{src:g(279)}})]),A._v(" "),I("div",{staticClass:"case-studies-inner-content"},[I("h1",[A._v("Trusted by the best")]),A._v(" "),I("p",{staticClass:"description"},[A._v("Innovative projects are building with LDK")]),A._v(" "),I("a",{attrs:{href:"/case-studies/"}},[A._v("All case studies ->")])])])]),A._v(" "),I("div",{staticClass:"cross-promo"},[I("a",{attrs:{href:"https://bitcoindevkit.org/"}},[I("div",{staticClass:"cross-promo-inner"},[I("img",{attrs:{src:g(366)}}),A._v(" "),I("div",{staticClass:"divider"}),A._v(" "),I("p",{staticClass:"cross-promo-description"},[A._v("The on-chain companion to LDK")])])])])])}),[],!1,null,null,null);I.default=t.exports}}]); \ No newline at end of file diff --git a/assets/js/12.3e9dbde3.js b/assets/js/12.3e9dbde3.js new file mode 100644 index 000000000..641e5e768 --- /dev/null +++ b/assets/js/12.3e9dbde3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{348:function(t,a,n){t.exports=n.p+"assets/img/qr-codes.58a16df5.png"},349:function(t,a,n){t.exports=n.p+"assets/img/blinded-path.2f9b76cf.svg"},350:function(t,a,n){t.exports=n.p+"assets/img/offers-flow.ccc79cd7.svg"},351:function(t,a,n){t.exports=n.p+"assets/img/offer-metadata.45a2a1cf.svg"},388:function(t,a,n){"use strict";n.r(a);var s=n(7),e=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("p",[t._v("You may have heard of BOLT12—lovingly referred to as Offers—but what is it, and why should you care? In short, BOLT12 is a new payment protocol for Lightning that offers enhanced privacy, reusable payment codes, refunds, and much more, all natively over the Lightning Network. No additional servers are required. This is all possible using new technologies like onion messages and route blinding. Let’s further explore how to make use of BOLT12 in LDK.")]),t._v(" "),a("h2",{attrs:{id:"bolt11-invoices-and-reusability"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bolt11-invoices-and-reusability"}},[t._v("#")]),t._v(" BOLT11 Invoices and Reusability")]),t._v(" "),a("p",[t._v("To understand why BOLT12 is essential, let’s briefly discuss what it’s replacing. BOLT11 defined an invoice format that, while useful, has some shortcomings. Invoices are communicated out-of-band—typically via a QR code—from recipient to sender. They are signed, making them large and thus difficult for some devices to scan. But more importantly, they can’t be safely reused since they contain a payment hash.")]),t._v(" "),a("p",[t._v("In Lightning, a payment is claimed by releasing the preimage of a payment hash. Once revealed, anyone with knowledge of the preimage—which could show up on-chain—may use it to claim a payment for an invoice using the same payment hash. So, reusing invoices is a no-no if you don’t want your payment stolen. While solutions have been built up around BOLT11 for requesting unique invoices, they have significant drawbacks. It requires either running a dedicated server or trusting a third party to do so on your behalf, including all the privacy implications that this entails.")]),t._v(" "),a("h2",{attrs:{id:"bolt12-to-the-rescue"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bolt12-to-the-rescue"}},[t._v("#")]),t._v(" BOLT12 to the Rescue")]),t._v(" "),a("p",[t._v("That’s where BOLT12 comes in. The specification defines an "),a("em",[t._v("offer")]),t._v(" that can be considered a precursor to an "),a("em",[t._v("invoice")]),t._v(". It contains less data than an invoice and is smaller to display as a QR code. Optionally, it may contain blinded paths—more on that in a moment. Someone scanning an offer sends an "),a("em",[t._v("invoice request")]),t._v(" to the intended recipient, who replies with an invoice containing a unique payment hash. That’s it!")]),t._v(" "),a("figure",[a("img",{attrs:{src:n(348),alt:"BOLT11 vs BOLT12 QR Codes"}})]),t._v(" "),a("p",{staticStyle:{"text-align":"center"}},[a("i",[t._v("Comparison of typical BOLT11 (left) and BOLT12 (right) QR codes")])]),t._v(" "),a("p",[t._v("So how is this all happening without a dedicated server? The magic comes in with something called "),a("a",{attrs:{href:"../onion-messages-demystified"}},[t._v("onion messages")]),t._v(". The Lightning protocol is defined as messages exchanged between direct peers. An onion payment involves an interchange of messages along a path, collecting fees and transferring funds until the preimage is revealed and the funds claimed.")]),t._v(" "),a("p",[t._v("An onion message is very similar in that it involves sending messages along a path, encrypted as an onion such that each hop only knows where to send the message next. The difference is that they’re more efficient and don’t require locking any liquidity. Messages are forwarded until they reach the intended recipient. There is no interchange between adjacent peers to sign and revoke commitments or a round-trip along the path. Channel liquidity—or channels, for that matter—aren’t even required.")]),t._v(" "),a("h2",{attrs:{id:"ok-so-what-about-privacy"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#ok-so-what-about-privacy"}},[t._v("#")]),t._v(" OK, so what about privacy?")]),t._v(" "),a("p",[t._v("Ah, that’s where blinded paths come in. BOLT11 invoices reveal the recipient's node ID, which could be mapped to their IP address. But remember how an offer may contain some blinded paths? Those are to ensure recipient privacy. The recipient constructs a path leading to itself from some point in the Lightning Network, probably a few hops away. Then, it blinds the nodes along the route using fancy cryptography, leaving the first node unblinded. We call that the introduction node.")]),t._v(" "),a("figure",[a("img",{attrs:{src:n(349),alt:"Blinded Path"}})]),t._v(" "),a("p",{staticStyle:{"text-align":"center"}},[a("i",[t._v("Depiction of a blinded path used in an offer where adjacent nodes are peers")])]),t._v(" "),a("p",[t._v("When the sender scans an offer, it constructs a path from itself to the blinded path’s introduction node. This combined path is then made into an onion for routing with the invoice request as the payload. It also contains a "),a("em",[t._v("reply path")]),t._v("—another blinded path—back to the sender, allowing the recipient to respond similarly to an invoice without revealing the sender’s node ID.")]),t._v(" "),a("p",[t._v("This is taken further with the invoice, which contains "),a("em",[t._v("blinded payment paths")]),t._v("—essentially blinded paths with some additional payment information. This allows the recipient to provide partial routes with enough liquidity for payment as requests are made—yet in a privacy-preserving manner, unlike BOLT11.")]),t._v(" "),a("figure",[a("img",{attrs:{src:n(350),alt:"Offers flow"}})]),t._v(" "),a("p",{staticStyle:{"text-align":"center"}},[a("i",[t._v("Offers flow of Alice paying Bob where onion messages and payments culminate over blinded paths")])]),t._v(" "),a("p",[t._v("Invoices and invoice requests are signed using keys corresponding to pubkeys in the offer and invoice request. But guess what? These can be unique since, in the presence of blinded paths, they aren’t needed for routing. By always generating new keys, payments are more difficult to correlate to the same sender or recipient, an added boon for privacy! Contrast this with a BOLT11 invoice containing the recipient’s node ID. This is so the sender can construct a route to the recipient for the payment.")]),t._v(" "),a("h2",{attrs:{id:"offers-in-ldk"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#offers-in-ldk"}},[t._v("#")]),t._v(" Offers in LDK")]),t._v(" "),a("p",[t._v("There’s a lot to BOLT12, but LDK helpfully hides all those details from you. Let’s take a look at how you would construct an offer in LDK using the familiar builder pattern.")]),t._v(" "),a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" offer "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_offer_builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("description")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"coffee"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("amount_msats")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10_000_000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bech32_offer "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" offer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("One cool thing about offers is that they can be stateless, meaning you don’t need to store any data about them once constructed. How does this work? LDK encodes some information in the offer’s metadata, allowing it to recognize incoming invoice requests for the offer.")]),t._v(" "),a("p",[t._v("Paying an offer is just as simple.")]),t._v(" "),a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" retry "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Retry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Timeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_secs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pay_for_offer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n offer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" quantity"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount_msats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payer_note"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" retry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" max_total_routing_fee_msat\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Requesting invoice for offer"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unable to request invoice for offer: {:?}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// First the payment will be waiting on an invoice")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" expected_payment_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("assert!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_recent_payments")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("details"),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("matches!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n details"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RecentPaymentDetails")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AwaitingInvoice")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" expected_payment_id "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("is_some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Once the invoice is received, a payment will be sent")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("assert!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_recent_payments")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("details"),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("matches!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n details"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RecentPaymentDetails")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pending")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" expected_payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("is_some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Here, LDK stores a small amount of data for outbound payments, which ensures you don’t pay an invoice more than once for a given payment ID.")]),t._v(" "),a("p",[t._v("As the recipient, you only need to wait for an event to claim the payment.")]),t._v(" "),a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[t._v("channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("process_pending_events")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("event"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentClaimable")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" purpose"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" purpose "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvoicePayment")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payment_preimage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Claiming payment {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("claim_funds")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payment_preimage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n \t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvoicePayment")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Unknown payment hash: {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentClaimed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Claimed {} msats"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Similarly, the sender will receive an event when the payment is resolved.")]),t._v(" "),a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[t._v("channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("process_pending_events")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("event"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentSent")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Paid {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentFailed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed paying {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvoiceRequestFailed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed paying {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("These examples work swimmingly when building a Lightning wallet programmatically. However, LDK uniquely exposes the underlying "),a("a",{attrs:{href:"https://docs.rs/lightning/0.0.123-beta/lightning/offers/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("offers"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://docs.rs/lightning/0.0.123-beta/lightning/blinded_path/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("blinded paths"),a("OutboundLink")],1),t._v(", and "),a("a",{attrs:{href:"https://docs.rs/lightning/0.0.123-beta/lightning/onion_message/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("onion message"),a("OutboundLink")],1),t._v(" modules for direct use. This means you can experiment with building your applications or add BOLT12 support to LND, such as the "),a("a",{attrs:{href:"https://github.com/lndk-org/lndk",target:"_blank",rel:"noopener noreferrer"}},[t._v("LNDK"),a("OutboundLink")],1),t._v(" project.")]),t._v(" "),a("h2",{attrs:{id:"wait-what-about-refunds"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#wait-what-about-refunds"}},[t._v("#")]),t._v(" Wait, what about refunds?")]),t._v(" "),a("p",[t._v("Whereas an offer is an “offer to be paid,” a "),a("em",[t._v("refund")]),t._v(" is an “offer for money.” Simply put, refunds allow a merchant to present a QR code to a customer to refund a purchase. The customer scans the refund just like it would an offer, but instead of sending the merchant an invoice request, the customer sends an invoice asking the merchant to pay.")]),t._v(" "),a("p",[t._v("LDK has a similar interface for constructing a refund and requesting payment.")]),t._v(" "),a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" retry "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Retry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Timeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_secs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" refund "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_refund_builder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n amount_msats"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" absolute_expiry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" retry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" max_total_routing_fee_msat\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("description")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"coffee"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payer_note")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"refund for order 1234"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bech32_refund "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" refund"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Like when paying an offer, LDK will track a pending payment and surface events just the same.")]),t._v(" "),a("h2",{attrs:{id:"achieving-statelessness"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#achieving-statelessness"}},[t._v("#")]),t._v(" Achieving statelessness")]),t._v(" "),a("p",[t._v("Both offer and invoice requests contain a metadata field. This helps LDK store minimal information about a payment. For inbound payments, this equals nothing at all! So how does it work?")]),t._v(" "),a("p",[t._v("LDK generates a random nonce for an offer and, along with the offer’s TLV records, computes an HMAC using a secret key. The HMAC is used to derive a key to sign the invoice. The nonce is then stored in the offer’s metadata to re-derive the signing key later.")]),t._v(" "),a("p",[t._v("When an invoice request is received, it contains all the offer’s TLV records, including the metadata. By re-deriving the signing key from the metadata and TLV records, LDK can verify that the offer is authentic by checking whether the re-derived signing key corresponds to the offer’s signing pubkey. Now, it can create and sign an invoice with the key.")]),t._v(" "),a("p",[t._v("If you prefer to use your signing key, LDK will also include the HMAC in the metadata. Authentication then consists of re-computing the HMAC and comparing it against the one in the metadata.")]),t._v(" "),a("p",[t._v("An invoice request has its own payer metadata, which is similarly generated and includes an encrypted payment ID. Thus, when LDK receives an invoice, it can look up a pending payment with the ID and decide if the invoice should be paid after a similar authentication.")]),t._v(" "),a("figure",[a("img",{attrs:{src:n(351),alt:"Offer metadata"}})]),t._v(" "),a("p",{staticStyle:{"text-align":"center"}},[a("i",[t._v("Metadata consists primarily of a nonce and an optional HMAC, while outbound payments include an encrypted payment ID used for look-up upon receiving an invoice")])]),t._v(" "),a("h2",{attrs:{id:"what-s-next"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#what-s-next"}},[t._v("#")]),t._v(" What’s next?")]),t._v(" "),a("p",[t._v("BOLT12 is still in a very early stage of adoption, but as you can see, there’s much promise. In the next post, we’ll explore one of the most crucial problems in Lightning—receiving offline—and how BOLT12 and asynchronous payments solve it.")])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/12.2f88c132.js b/assets/js/13.94ab44a3.js similarity index 93% rename from assets/js/12.2f88c132.js rename to assets/js/13.94ab44a3.js index ca802cab1..8a64d555a 100644 --- a/assets/js/12.2f88c132.js +++ b/assets/js/13.94ab44a3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{352:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-1.8264e375.png"},353:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-2.e3e05fcb.png"},354:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-3.fd401501.png"},355:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-4.934aee81.png"},389:function(e,t,n){"use strict";n.r(t);var o=n(7),s=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("We recently merged support for onion message forwarding, a precursor to deprecating today’s Lightning invoice format, in favor of "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/798",target:"_blank",rel:"noopener noreferrer"}},[e._v("offers"),t("OutboundLink")],1),e._v(". Offers bring many improvements to Lightning, including static invoices, refunds, and receiving payments in a way that doesn’t reveal your node ID or UTXOs. Then, once offer extensions are added, support for subscriptions follows.")]),e._v(" "),t("p",[e._v("So a lot is happening. Including…")]),e._v(" "),t("p",[e._v("Once the network supports "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/ptlc/",target:"_blank",rel:"noopener noreferrer"}},[e._v("PTLCs"),t("OutboundLink")],1),e._v(", onion messages will help enable "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("asynchronous Lightning payments"),t("OutboundLink")],1),e._v(" that remove the rule requiring nodes to be online when receiving payments. We expect onion messages to provide a better foundation for noncustodial Lightning payment UX, including privacy bonuses.")]),e._v(" "),t("h2",{attrs:{id:"how-onion-messages-work"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#how-onion-messages-work"}},[e._v("#")]),e._v(" How Onion Messages Work")]),e._v(" "),t("p",[e._v("Onion messages are lightweight, flexible messages sent between Lightning Network peers using onion routing. Unlike today’s payment messages, peers may send onion messages along a blinded route, thus concealing the recipient’s info. But what’s a blinded route?")]),e._v(" "),t("h2",{attrs:{id:"blinded-routes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#blinded-routes"}},[e._v("#")]),e._v(" Blinded Routes")]),e._v(" "),t("p",[e._v("If Alice doesn’t want to reveal lots of personal information about her channels and UTXOs, she can use cryptography to create an obfuscated or “blinded” route to herself for the sender (we’ll call him Bob) to send an onion message along. To construct this route, she’ll first find a route to herself from some PopularNode in the graph that has a lot of peers.")]),e._v(" "),t("p",[e._v("By selecting PopularNode from this network chart, Alice’s anonymity set includes all highlighted peers:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(352),alt:"OM"}})]),e._v(" "),t("p",[e._v("To Bob and any other observers, any node within two hops of PopularNode could be the destination of the onion message. Adding more hops further expands Alice’s anonymity set. (Note that PopularNode’s direct peers are candidates because blinded routes may contain fake dummy hops.)")]),e._v(" "),t("p",[e._v("After selecting the path from PopularNode, she’ll create an encrypted blob for each hop that contains information about reaching the next hop, which ends at her node. At this point, the blinded route looks like this:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(353),alt:"OM"}})]),e._v(" "),t("p",[e._v("Finally, she’ll provide this blinded route to Bob, who will find a route to PopularNode and use Alice’s blinded route when constructing the last three hop payloads within the onion packet.")]),e._v(" "),t("h2",{attrs:{id:"onion-message-structure"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#onion-message-structure"}},[e._v("#")]),e._v(" Onion Message Structure")]),e._v(" "),t("p",[e._v("Continuing with this example, let’s say Bob finds this path to Alice’s blinded route:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(354),alt:"OM"}})]),e._v(" "),t("p",[e._v("If Bob sends an invoice request through Alice’s blinded route via onion message, his message would look like this:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(355),alt:"OM"}})]),e._v(" "),t("p",[e._v("So each intermediate layer of the onion contains encrypted forwarding information for the next hop, and the last layer contains the content of the onion message intended for the final hop. This content may include invoice requests and invoices for offers.")]),e._v(" "),t("h2",{attrs:{id:"beyond-offers-asynchronous-payments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#beyond-offers-asynchronous-payments"}},[e._v("#")]),e._v(" Beyond Offers: Asynchronous Payments")]),e._v(" "),t("p",[e._v("While offers were the original point of onion messages, their flexible format unlocks further opportunities to improve the Lightning Network.")]),e._v(" "),t("p",[e._v("For context, a significant problem facing the Lightning Network is that users running noncustodial Lightning wallets on phones must have their wallet app in the foreground to receive payments. This is a big departure from the Cash App-like UX that users want and even expect.")]),e._v(" "),t("p",[e._v("A key part of the solution here is for mobile wallets to have always-online channel counterparties. These counterparties are likely to be Lightning Service Providers (LSPs), which manage channel liquidity and stay online on behalf of end users, but they may be any always-online node.")]),e._v(" "),t("p",[e._v("Enter asynchronous Lightning payments. Async payments utilize always-online channel counterparties on both ends, sender and receiver. The sender’s counterparty will hold onto a payment until it receives an onion message from the recipient's counterparty indicating the recipient is online and ready to receive funds. At this point, the sender’s counterparty releases the payment. Note that the sender's \"counterparty\" may be the sender themselves, if they are always online and sending to an\noften-offline receiver.")]),e._v(" "),t("p",[e._v("While it may sound like it, this does not tie up network liquidity via long CLTV timeouts like today's \"async payments\" because the only locked liquidity is the sender's, and the sender has already bid farewell to those funds.")]),e._v(" "),t("p",[e._v("For more information, "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("follow the development of async payments"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"future-security-directions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#future-security-directions"}},[e._v("#")]),e._v(" Future Security Directions")]),e._v(" "),t("p",[e._v("The concept of onion messages might make you ask: “Free, flexible messages? What if there’s a ton of spam, or people stream videos over Lightning?”")]),e._v(" "),t("p",[e._v("The good news is that there are many ways to rate limit onion messages. For example, limiting peers to a few kilobytes worth of onion messages per second would not be enough bandwidth to allow for streaming. You can also restrict forwarded onion messages to channel peers only, meaning that even if someone attempted a full-on DoS attack, they would be forced to open a great deal of channels.")]),e._v(" "),t("p",[e._v("For more information, see this "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-June/003623.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("mailing list post and replies"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"seeya"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#seeya"}},[e._v("#")]),e._v(" Seeya")]),e._v(" "),t("p",[e._v("Thanks for taking the time to learn about onion messages and their use cases. We think it’s a big first step towards a grandparent-friendly noncustodial Lightning UX.")]),e._v(" "),t("p",[e._v("Want to contribute to LDK? Join us on GitHub at our "),t("a",{attrs:{href:"https://github.com/lightningdevkit/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK repo"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{356:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-1.8264e375.png"},357:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-2.e3e05fcb.png"},358:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-3.fd401501.png"},359:function(e,t,n){e.exports=n.p+"assets/img/OM-dm-image-4.934aee81.png"},395:function(e,t,n){"use strict";n.r(t);var o=n(7),s=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("We recently merged support for onion message forwarding, a precursor to deprecating today’s Lightning invoice format, in favor of "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/798",target:"_blank",rel:"noopener noreferrer"}},[e._v("offers"),t("OutboundLink")],1),e._v(". Offers bring many improvements to Lightning, including static invoices, refunds, and receiving payments in a way that doesn’t reveal your node ID or UTXOs. Then, once offer extensions are added, support for subscriptions follows.")]),e._v(" "),t("p",[e._v("So a lot is happening. Including…")]),e._v(" "),t("p",[e._v("Once the network supports "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/ptlc/",target:"_blank",rel:"noopener noreferrer"}},[e._v("PTLCs"),t("OutboundLink")],1),e._v(", onion messages will help enable "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("asynchronous Lightning payments"),t("OutboundLink")],1),e._v(" that remove the rule requiring nodes to be online when receiving payments. We expect onion messages to provide a better foundation for noncustodial Lightning payment UX, including privacy bonuses.")]),e._v(" "),t("h2",{attrs:{id:"how-onion-messages-work"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#how-onion-messages-work"}},[e._v("#")]),e._v(" How Onion Messages Work")]),e._v(" "),t("p",[e._v("Onion messages are lightweight, flexible messages sent between Lightning Network peers using onion routing. Unlike today’s payment messages, peers may send onion messages along a blinded route, thus concealing the recipient’s info. But what’s a blinded route?")]),e._v(" "),t("h2",{attrs:{id:"blinded-routes"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#blinded-routes"}},[e._v("#")]),e._v(" Blinded Routes")]),e._v(" "),t("p",[e._v("If Alice doesn’t want to reveal lots of personal information about her channels and UTXOs, she can use cryptography to create an obfuscated or “blinded” route to herself for the sender (we’ll call him Bob) to send an onion message along. To construct this route, she’ll first find a route to herself from some PopularNode in the graph that has a lot of peers.")]),e._v(" "),t("p",[e._v("By selecting PopularNode from this network chart, Alice’s anonymity set includes all highlighted peers:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(356),alt:"OM"}})]),e._v(" "),t("p",[e._v("To Bob and any other observers, any node within two hops of PopularNode could be the destination of the onion message. Adding more hops further expands Alice’s anonymity set. (Note that PopularNode’s direct peers are candidates because blinded routes may contain fake dummy hops.)")]),e._v(" "),t("p",[e._v("After selecting the path from PopularNode, she’ll create an encrypted blob for each hop that contains information about reaching the next hop, which ends at her node. At this point, the blinded route looks like this:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(357),alt:"OM"}})]),e._v(" "),t("p",[e._v("Finally, she’ll provide this blinded route to Bob, who will find a route to PopularNode and use Alice’s blinded route when constructing the last three hop payloads within the onion packet.")]),e._v(" "),t("h2",{attrs:{id:"onion-message-structure"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#onion-message-structure"}},[e._v("#")]),e._v(" Onion Message Structure")]),e._v(" "),t("p",[e._v("Continuing with this example, let’s say Bob finds this path to Alice’s blinded route:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(358),alt:"OM"}})]),e._v(" "),t("p",[e._v("If Bob sends an invoice request through Alice’s blinded route via onion message, his message would look like this:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(359),alt:"OM"}})]),e._v(" "),t("p",[e._v("So each intermediate layer of the onion contains encrypted forwarding information for the next hop, and the last layer contains the content of the onion message intended for the final hop. This content may include invoice requests and invoices for offers.")]),e._v(" "),t("h2",{attrs:{id:"beyond-offers-asynchronous-payments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#beyond-offers-asynchronous-payments"}},[e._v("#")]),e._v(" Beyond Offers: Asynchronous Payments")]),e._v(" "),t("p",[e._v("While offers were the original point of onion messages, their flexible format unlocks further opportunities to improve the Lightning Network.")]),e._v(" "),t("p",[e._v("For context, a significant problem facing the Lightning Network is that users running noncustodial Lightning wallets on phones must have their wallet app in the foreground to receive payments. This is a big departure from the Cash App-like UX that users want and even expect.")]),e._v(" "),t("p",[e._v("A key part of the solution here is for mobile wallets to have always-online channel counterparties. These counterparties are likely to be Lightning Service Providers (LSPs), which manage channel liquidity and stay online on behalf of end users, but they may be any always-online node.")]),e._v(" "),t("p",[e._v("Enter asynchronous Lightning payments. Async payments utilize always-online channel counterparties on both ends, sender and receiver. The sender’s counterparty will hold onto a payment until it receives an onion message from the recipient's counterparty indicating the recipient is online and ready to receive funds. At this point, the sender’s counterparty releases the payment. Note that the sender's \"counterparty\" may be the sender themselves, if they are always online and sending to an\noften-offline receiver.")]),e._v(" "),t("p",[e._v("While it may sound like it, this does not tie up network liquidity via long CLTV timeouts like today's \"async payments\" because the only locked liquidity is the sender's, and the sender has already bid farewell to those funds.")]),e._v(" "),t("p",[e._v("For more information, "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("follow the development of async payments"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"future-security-directions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#future-security-directions"}},[e._v("#")]),e._v(" Future Security Directions")]),e._v(" "),t("p",[e._v("The concept of onion messages might make you ask: “Free, flexible messages? What if there’s a ton of spam, or people stream videos over Lightning?”")]),e._v(" "),t("p",[e._v("The good news is that there are many ways to rate limit onion messages. For example, limiting peers to a few kilobytes worth of onion messages per second would not be enough bandwidth to allow for streaming. You can also restrict forwarded onion messages to channel peers only, meaning that even if someone attempted a full-on DoS attack, they would be forced to open a great deal of channels.")]),e._v(" "),t("p",[e._v("For more information, see this "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-June/003623.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("mailing list post and replies"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"seeya"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#seeya"}},[e._v("#")]),e._v(" Seeya")]),e._v(" "),t("p",[e._v("Thanks for taking the time to learn about onion messages and their use cases. We think it’s a big first step towards a grandparent-friendly noncustodial Lightning UX.")]),e._v(" "),t("p",[e._v("Want to contribute to LDK? Join us on GitHub at our "),t("a",{attrs:{href:"https://github.com/lightningdevkit/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK repo"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/13.089e0b9a.js b/assets/js/14.29d717bf.js similarity index 60% rename from assets/js/13.089e0b9a.js rename to assets/js/14.29d717bf.js index 3fb80ba4a..92489b0f2 100644 --- a/assets/js/13.089e0b9a.js +++ b/assets/js/14.29d717bf.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{323:function(t,e,n){},365:function(t,e,n){"use strict";n(323)},432:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:(t,{props:e,slots:n})=>t("span",{class:["badge",e.type],style:{verticalAlign:e.vertical}},e.text||n().default)},p=(n(365),n(7)),l=Object(p.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=l.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{323:function(t,e,n){},369:function(t,e,n){"use strict";n(323)},437:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:(t,{props:e,slots:n})=>t("span",{class:["badge",e.type],style:{verticalAlign:e.vertical}},e.text||n().default)},p=(n(369),n(7)),l=Object(p.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/14.9ca80667.js b/assets/js/15.9b4e9bd8.js similarity index 65% rename from assets/js/14.9ca80667.js rename to assets/js/15.9b4e9bd8.js index 8b312e257..999f7218e 100644 --- a/assets/js/14.9ca80667.js +++ b/assets/js/15.9b4e9bd8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{324:function(t,e,a){},366:function(t,e,a){"use strict";a(324)},378:function(t,e,a){"use strict";a.r(e);var s={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(366),a(7)),n=Object(i.a)(s,(function(){return(0,this._self._c)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{324:function(t,e,a){},370:function(t,e,a){"use strict";a(324)},382:function(t,e,a){"use strict";a.r(e);var s={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(370),a(7)),n=Object(i.a)(s,(function(){return(0,this._self._c)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/15.291cacc3.js b/assets/js/16.41c244cb.js similarity index 88% rename from assets/js/15.291cacc3.js rename to assets/js/16.41c244cb.js index 152f7e60f..bb92979d2 100644 --- a/assets/js/15.291cacc3.js +++ b/assets/js/16.41c244cb.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{325:function(e,t,a){},367:function(e,t,a){"use strict";a(325)},379:function(e,t,a){"use strict";a.r(t);var o={name:"CodeGroup",data:()=>({codeTabs:[],activeCodeTabIndex:-1}),watch:{activeCodeTabIndex(e){this.activateCodeTab(e)}},mounted(){this.loadTabs()},methods:{changeCodeTab(e){this.activeCodeTabIndex=e},loadTabs(){this.codeTabs=(this.$slots.default||[]).filter(e=>Boolean(e.componentOptions)).map((e,t)=>(""===e.componentOptions.propsData.active&&(this.activeCodeTabIndex=t),{title:e.componentOptions.propsData.title,elm:e.elm})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab(e){this.codeTabs.forEach(e=>{e.elm&&e.elm.classList.remove("theme-code-block__active")}),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},s=(a(367),a(7)),c=Object(s.a)(o,(function(){var e=this,t=e._self._c;return t("ClientOnly",[t("div",{staticClass:"theme-code-group"},[t("div",{staticClass:"theme-code-group__nav"},[t("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(a,o){return t("li",{key:a.title,staticClass:"theme-code-group__li"},[t("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(a.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?t("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{325:function(e,t,a){},371:function(e,t,a){"use strict";a(325)},383:function(e,t,a){"use strict";a.r(t);var o={name:"CodeGroup",data:()=>({codeTabs:[],activeCodeTabIndex:-1}),watch:{activeCodeTabIndex(e){this.activateCodeTab(e)}},mounted(){this.loadTabs()},methods:{changeCodeTab(e){this.activeCodeTabIndex=e},loadTabs(){this.codeTabs=(this.$slots.default||[]).filter(e=>Boolean(e.componentOptions)).map((e,t)=>(""===e.componentOptions.propsData.active&&(this.activeCodeTabIndex=t),{title:e.componentOptions.propsData.title,elm:e.elm})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab(e){this.codeTabs.forEach(e=>{e.elm&&e.elm.classList.remove("theme-code-block__active")}),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},s=(a(371),a(7)),c=Object(s.a)(o,(function(){var e=this,t=e._self._c;return t("ClientOnly",[t("div",{staticClass:"theme-code-group"},[t("div",{staticClass:"theme-code-group__nav"},[t("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(a,o){return t("li",{key:a.title,staticClass:"theme-code-group__li"},[t("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(a.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?t("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file diff --git a/assets/js/16.97c6e1e8.js b/assets/js/17.a5a186e3.js similarity index 94% rename from assets/js/16.97c6e1e8.js rename to assets/js/17.a5a186e3.js index fe1daf7f4..6ff317ddf 100644 --- a/assets/js/16.97c6e1e8.js +++ b/assets/js/17.a5a186e3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{349:function(e,t,n){e.exports=n.p+"assets/img/phantom-hints.64e934b6.png"},350:function(e,t,n){e.exports=n.p+"assets/img/phantom-pmt.8d872436.png"},386:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Introducing phantom node payments, a new-ish feature for LDK.")]),e._v(" "),t("p",[e._v("Phantom node payments let enterprise users running high-volume lightning nodes generate invoices that can be paid to one of multiple production nodes. Since it’s safe to assume that payers will retry along an alternate route hint if one fails, phantom payments allow for load balancing between nodes and resilience if a node or nodes go down.")]),e._v(" "),t("h2",{attrs:{id:"phantom-payment-flow"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#phantom-payment-flow"}},[e._v("#")]),e._v(" Phantom Payment Flow")]),e._v(" "),t("p",[e._v("Using LNMerchant as an example company, here’s how phantom payments work:")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Buyer on the Lightning Network requests an invoice")])]),e._v(" "),t("li",[t("p",[e._v("LNMerchant replies with an invoice. Per standard invoice protocol, it contains information on routing to LNMerchant. However, unlike conventional invoice route hints, phantom route hints include a combination of real and fake routing information. This fake or “phantom” routing information will later signal to LDK that the payment’s intended destination is a phantom node.")])])]),e._v(" "),t("p",[e._v("The following illustration demonstrates how phantom route hints work:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(349),alt:"Phantom Hints"}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("The buyer’s node generates a normal route. Using the route hints, the last two hops are [LNMerchantNode, PhantomNode], i.e., the phantom node is the destination node, and the second-to-last hop is an actual LNMerchant node. (Note: If the LNMerchant has public channels, only the last hop containing the fake channel is strictly necessary for the route hints.)")])]),e._v(" "),t("p",[e._v("The buyer uses this route, including the fake forwarding information from the route hints, to generate the payment onion. On Lightning, each hop along the route unwraps one layer of sender-constructed onion.")]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[t("p",[e._v("The buyer forwards the payment to the route’s first hop, which gets forwarded through intermediate hops.")])]),e._v(" "),t("li",[t("p",[e._v("The payment forwards to the second-to-last hop, an actual LNMerchant node.")])]),e._v(" "),t("li",[t("p",[e._v("The LNMerchant node checks what channel to forward the payment to and recognizes a phantom channel ID.")])]),e._v(" "),t("li",[t("p",[e._v("The LNMerchant node knows the phantom node’s secret key, so it can unwrap the last layer of the onion and verify the payment details. It also knows the preimage for the payment, so it can claim the amount owed without forwarding the payment to the non-existent phantom.")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:n(350),alt:"Phantom PMT"}})]),e._v(" "),t("h2",{attrs:{id:"why-it-s-ok-to-not-support-mpp"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-it-s-ok-to-not-support-mpp"}},[e._v("#")]),e._v(" Why It’s OK to Not Support MPP")]),e._v(" "),t("p",[e._v("One potential drawback to phantom node payments is the lack of multi-path payments (MPP) support.")]),e._v(" "),t("p",[e._v("MPP payments benefit large transactions because they aren’t restricted to routes where each channel must carry its entire payment balance.")]),e._v(" "),t("p",[e._v("With this in mind, a compelling compromise is to:")]),e._v(" "),t("ul",[t("li",[e._v("Create MPP-supporting invoices against a single node for large payments.")]),e._v(" "),t("li",[e._v("Create phantom invoices for smaller payments, which are the most common and are unlikely to use MPP.")])]),e._v(" "),t("h2",{attrs:{id:"why-mpp-shouldn-t-be-enabled"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-mpp-shouldn-t-be-enabled"}},[e._v("#")]),e._v(" Why MPP Shouldn’t Be Enabled")]),e._v(" "),t("p",[e._v("Let’s say that we want to implement MPP for phantom payments. In this case, each real LNMerchant node may receive a slice of the phantom node-destined phantom payment. In this case, the question becomes: How do real nodes know when a payment is accepted across all nodes so that it’s safe to release the preimage?")]),e._v(" "),t("p",[e._v("On the surface, it seems like users should be able to tell LDK when a payment has been received across all nodes and is safe to claim. However, this would significantly compromise our safety guarantees because releasing the preimage before receiving the total payment value opens up the possibility for intermediate nodes to claim remaining payment parts. Moreover, implementing this would introduce perilous race conditions, because users would need to “lock” internal LDK data structures to ensure payment claims are atomic. Failing to properly handle these delicate cases would lead to force-closed channels and possibly lost funds.")]),e._v(" "),t("hr"),e._v(" "),t("p",[e._v("Thanks for taking the time to learn about phantom nodes and payments. We think it’s an exciting showcase for the lightning protocol’s flexibility and variety of use cases.")]),e._v(" "),t("p",[e._v("Want to make your own contribution to LDK? Join us on GitHub at our "),t("a",{attrs:{href:"https://github.com/lightningdevkit/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK repo"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{353:function(e,t,n){e.exports=n.p+"assets/img/phantom-hints.64e934b6.png"},354:function(e,t,n){e.exports=n.p+"assets/img/phantom-pmt.8d872436.png"},391:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Introducing phantom node payments, a new-ish feature for LDK.")]),e._v(" "),t("p",[e._v("Phantom node payments let enterprise users running high-volume lightning nodes generate invoices that can be paid to one of multiple production nodes. Since it’s safe to assume that payers will retry along an alternate route hint if one fails, phantom payments allow for load balancing between nodes and resilience if a node or nodes go down.")]),e._v(" "),t("h2",{attrs:{id:"phantom-payment-flow"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#phantom-payment-flow"}},[e._v("#")]),e._v(" Phantom Payment Flow")]),e._v(" "),t("p",[e._v("Using LNMerchant as an example company, here’s how phantom payments work:")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Buyer on the Lightning Network requests an invoice")])]),e._v(" "),t("li",[t("p",[e._v("LNMerchant replies with an invoice. Per standard invoice protocol, it contains information on routing to LNMerchant. However, unlike conventional invoice route hints, phantom route hints include a combination of real and fake routing information. This fake or “phantom” routing information will later signal to LDK that the payment’s intended destination is a phantom node.")])])]),e._v(" "),t("p",[e._v("The following illustration demonstrates how phantom route hints work:")]),e._v(" "),t("figure",[t("img",{attrs:{src:n(353),alt:"Phantom Hints"}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("The buyer’s node generates a normal route. Using the route hints, the last two hops are [LNMerchantNode, PhantomNode], i.e., the phantom node is the destination node, and the second-to-last hop is an actual LNMerchant node. (Note: If the LNMerchant has public channels, only the last hop containing the fake channel is strictly necessary for the route hints.)")])]),e._v(" "),t("p",[e._v("The buyer uses this route, including the fake forwarding information from the route hints, to generate the payment onion. On Lightning, each hop along the route unwraps one layer of sender-constructed onion.")]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[t("p",[e._v("The buyer forwards the payment to the route’s first hop, which gets forwarded through intermediate hops.")])]),e._v(" "),t("li",[t("p",[e._v("The payment forwards to the second-to-last hop, an actual LNMerchant node.")])]),e._v(" "),t("li",[t("p",[e._v("The LNMerchant node checks what channel to forward the payment to and recognizes a phantom channel ID.")])]),e._v(" "),t("li",[t("p",[e._v("The LNMerchant node knows the phantom node’s secret key, so it can unwrap the last layer of the onion and verify the payment details. It also knows the preimage for the payment, so it can claim the amount owed without forwarding the payment to the non-existent phantom.")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:n(354),alt:"Phantom PMT"}})]),e._v(" "),t("h2",{attrs:{id:"why-it-s-ok-to-not-support-mpp"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-it-s-ok-to-not-support-mpp"}},[e._v("#")]),e._v(" Why It’s OK to Not Support MPP")]),e._v(" "),t("p",[e._v("One potential drawback to phantom node payments is the lack of multi-path payments (MPP) support.")]),e._v(" "),t("p",[e._v("MPP payments benefit large transactions because they aren’t restricted to routes where each channel must carry its entire payment balance.")]),e._v(" "),t("p",[e._v("With this in mind, a compelling compromise is to:")]),e._v(" "),t("ul",[t("li",[e._v("Create MPP-supporting invoices against a single node for large payments.")]),e._v(" "),t("li",[e._v("Create phantom invoices for smaller payments, which are the most common and are unlikely to use MPP.")])]),e._v(" "),t("h2",{attrs:{id:"why-mpp-shouldn-t-be-enabled"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-mpp-shouldn-t-be-enabled"}},[e._v("#")]),e._v(" Why MPP Shouldn’t Be Enabled")]),e._v(" "),t("p",[e._v("Let’s say that we want to implement MPP for phantom payments. In this case, each real LNMerchant node may receive a slice of the phantom node-destined phantom payment. In this case, the question becomes: How do real nodes know when a payment is accepted across all nodes so that it’s safe to release the preimage?")]),e._v(" "),t("p",[e._v("On the surface, it seems like users should be able to tell LDK when a payment has been received across all nodes and is safe to claim. However, this would significantly compromise our safety guarantees because releasing the preimage before receiving the total payment value opens up the possibility for intermediate nodes to claim remaining payment parts. Moreover, implementing this would introduce perilous race conditions, because users would need to “lock” internal LDK data structures to ensure payment claims are atomic. Failing to properly handle these delicate cases would lead to force-closed channels and possibly lost funds.")]),e._v(" "),t("hr"),e._v(" "),t("p",[e._v("Thanks for taking the time to learn about phantom nodes and payments. We think it’s an exciting showcase for the lightning protocol’s flexibility and variety of use cases.")]),e._v(" "),t("p",[e._v("Want to make your own contribution to LDK? Join us on GitHub at our "),t("a",{attrs:{href:"https://github.com/lightningdevkit/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK repo"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/17.8236aa37.js b/assets/js/18.06dcfb51.js similarity index 85% rename from assets/js/17.8236aa37.js rename to assets/js/18.06dcfb51.js index 9adc38b2d..deb453f59 100644 --- a/assets/js/17.8236aa37.js +++ b/assets/js/18.06dcfb51.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{251:function(t,a){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},375:function(t,a,e){"use strict";e.r(a);var s=e(259),n=e(251),i={name:"FrontmatterKey",components:{LayoutWrap:s.a},computed:{items(){return this.$frontmatterKey.list}},methods:{displayName(t){return this.$page.path.startsWith("/blog/tags/")?Object(n.capitalize)(t):t}}},r=e(7),o=Object(r.a)(i,(function(){var t=this,a=t._self._c;return a("LayoutWrap",[a("main",{staticClass:"page"},[a("div",{staticClass:"theme-default-content"},[this.$page.path.startsWith("/blog/tags/")?a("h1",[t._v("Tags")]):a("h1",[t._v("Authors")]),t._v(" "),a("ul",t._l(t.items,(function(e){return a("li",{key:e.name},[a("router-link",{attrs:{to:e.path}},[t._v(t._s(t.displayName(e.name)))])],1)})),0)])])])}),[],!1,null,null,null);a.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{251:function(t,a){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},379:function(t,a,e){"use strict";e.r(a);var s=e(259),n=e(251),i={name:"FrontmatterKey",components:{LayoutWrap:s.a},computed:{items(){return this.$frontmatterKey.list}},methods:{displayName(t){return this.$page.path.startsWith("/blog/tags/")?Object(n.capitalize)(t):t}}},r=e(7),o=Object(r.a)(i,(function(){var t=this,a=t._self._c;return a("LayoutWrap",[a("main",{staticClass:"page"},[a("div",{staticClass:"theme-default-content"},[this.$page.path.startsWith("/blog/tags/")?a("h1",[t._v("Tags")]):a("h1",[t._v("Authors")]),t._v(" "),a("ul",t._l(t.items,(function(e){return a("li",{key:e.name},[a("router-link",{attrs:{to:e.path}},[t._v(t._s(t.displayName(e.name)))])],1)})),0)])])])}),[],!1,null,null,null);a.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/18.39dc46ce.js b/assets/js/19.6bcf995d.js similarity index 98% rename from assets/js/18.39dc46ce.js rename to assets/js/19.6bcf995d.js index 43c9e8f3a..3e10c17cc 100644 --- a/assets/js/18.39dc46ce.js +++ b/assets/js/19.6bcf995d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{347:function(e,t,i){e.exports=i.p+"assets/img/bitkit-architecture.be0e1a6b.png"},384:function(e,t,i){"use strict";i.r(t);var n=i(7),a=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("In 2020, the Lightning Network was in its early stages, and most people used custodial wallets. We believe this trend towards custodial wallets contradicts the Bitcoin ethos, so we decided to create a self-custodial alternative that offers a great user experience for all, not just technical users.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bitkit.to/",target:"_blank",rel:"noopener noreferrer"}},[e._v("And that's how Bitkit was born."),t("OutboundLink")],1)]),e._v(" "),t("h1",{attrs:{id:"before-ldk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#before-ldk"}},[e._v("#")]),e._v(" Before LDK")]),e._v(" "),t("p",[e._v("Choosing your tech stack is always challenging. When we first looked into the available Lightning Network implementations, we faced a difficult decision.")]),e._v(" "),t("p",[e._v("Rust-lightning, now known as LDK, had a promising modular architecture but was still in the early stages of development. We considered developing an implementation from scratch to meet Bitkit's specific needs, akin to Acinq's approach with Eclair, but other priorities led us to set this option aside. Ultimately, we adopted LND, the most prevalent implementation at the time. Breez had successfully showcased its potential, making it a logical choice for our stack.")]),e._v(" "),t("p",[e._v("We used LND as the backbone of Bitkit for more than a year, but one aspect stood in the way of providing an optimal user experience: the initialization time. LND utilizes Neutrino, a light Bitcoin client that downloads compact block filters to synchronize with the blockchain. Although it provides better privacy than Electrum Server or Esplora, it's not as fast.")]),e._v(" "),t("p",[e._v("The implications of the initial synchronization time extended well beyond waiting a few seconds. The longer the app stays closed, the longer the synchronization time. We often impatiently closed the app before it finished syncing, causing it to stay out of sync permanently. When we waited for it to fully synchronize, we often found our channel closed, forcing us to start over.")]),e._v(" "),t("p",[e._v("If we were frustrated, Bitkit users would be, too. This reminded us of the second-order effects caused by the technology stacked into our products. John, our CEO, said, “We can’t do this to our users.”")]),e._v(" "),t("p",[e._v("LND was not designed to be modular, making it challenging to swap out Neutrino. To provide the user experience we wanted, we'd need to develop Bitkit on top of a more flexible library. Otherwise, the user experience of self-custodial wallets would continue to fall short, and custodial wallets would remain more popular.")]),e._v(" "),t("p",[e._v("Meanwhile, LDK had come a long way since the early Rust-Lightning days. After revisiting it, its mobile-friendliness convinced us it was the right path forward. The switching cost was high, but we believed our decision would pay off in the long run. So we archived our "),t("a",{attrs:{href:"https://github.com/synonymdev/react-native-lightning",target:"_blank",rel:"noopener noreferrer"}},[e._v("React Native Lightning library"),t("OutboundLink")],1),e._v(" and merged a "),t("a",{attrs:{href:"https://github.com/synonymdev/bitkit/pull/146",target:"_blank",rel:"noopener noreferrer"}},[e._v("pull request"),t("OutboundLink")],1),e._v(", subtracting more than a year of work.")]),e._v(" "),t("p",[e._v("It was time for LDK.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did")]),e._v(" "),t("p",[e._v("Bitkit is built on React Native, and LDK primarily supports Kotlin and Swift bindings. Not to mention, there wasn't an off-the-shelf "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/announcing-ldk-node/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node"),t("OutboundLink")],1),e._v(" available back then. This led us to develop the "),t("a",{attrs:{href:"https://github.com/synonymdev/react-native-ldk",target:"_blank",rel:"noopener noreferrer"}},[e._v("React Native LDK library"),t("OutboundLink")],1),e._v(" from the ground up, which has since been adopted by "),t("a",{attrs:{href:"https://github.com/EttaWallet/EttaWallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Etta"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://github.com/bennyhodl/baywallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bay"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("By the time we decided to implement LDK, we had already built an on-chain wallet into Bitkit. LDK's flexibility allowed us to preserve it while we focused on rebuilding the Lightning logic.")]),e._v(" "),t("p",[e._v("We've recently "),t("a",{attrs:{href:"https://github.com/synonymdev/bitkit/pull/1450",target:"_blank",rel:"noopener noreferrer"}},[e._v("refactored the on-chain logic out of Bitkit"),t("OutboundLink")],1),e._v(" into a library, and LDK once again made it easy to retain the required methods and pass them through as needed.")]),e._v(" "),t("p",[e._v("We've also developed a custom "),t("a",{attrs:{href:"https://lightningdevkit.org/key_management/",target:"_blank",rel:"noopener noreferrer"}},[e._v("key manager"),t("OutboundLink")],1),e._v(" so the outputs of channel closure transactions get spent directly to Bitkit's on-chain wallet, removing the need for a costly sweeping transaction.")]),e._v(" "),t("p",[e._v("Throughout both on-chain wallet migrations, LDK enabled us to use Electrum Servers as the source of blockchain data, significantly reducing the initial sync time we've previously encountered.")]),e._v(" "),t("p",[e._v("To further minimize initialization delays, we started using LDK's "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/announcing-rapid-gossip-sync/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync"),t("OutboundLink")],1),e._v(". It skips client-side signature verification and compresses graph data, shrinking the required bandwidth and CPU resources. Without RGS, the easiest alternative to achieve fast initialization would be delegating routing to our servers, revealing users' payment destinations. With RGS, pathfinding is fast and client-side, preserving Lightning's privacy properties.")]),e._v(" "),t("p",[e._v("The customizability of the "),t("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/struct.ProbabilisticScorer.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("probabilistic scorer"),t("OutboundLink")],1),e._v(" parameters allowed us to further improve route-finding, translating into a higher payment success rate for users.")]),e._v(" "),t("p",[e._v("In addition, we've architected a custom backup server to meet Bitkit's specific requirements, which LDK was flexible enough to accommodate.")]),e._v(" "),t("figure",[t("img",{attrs:{src:i(347),alt:"Bitkit architecture"}})]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("Migrating to LDK wasn't an easy decision, but time has proven it to be the correct one. The support from the Spiral team was instrumental in easing the migration.")]),e._v(" "),t("p",[e._v("LDK enables us to focus on building a great wallet instead of getting bogged down by the complexities of the Lightning Network protocol.")]),e._v(" "),t("p",[e._v("Ultimately, LDK helps us to narrow the user experience gap between custodial and self-custodial wallets. As long as the lack of options leads people to rely on custodians, LDK will be pivotal in helping us to build a better alternative.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{347:function(e,t,i){e.exports=i.p+"assets/img/bitkit-architecture.be0e1a6b.png"},387:function(e,t,i){"use strict";i.r(t);var n=i(7),a=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("In 2020, the Lightning Network was in its early stages, and most people used custodial wallets. We believe this trend towards custodial wallets contradicts the Bitcoin ethos, so we decided to create a self-custodial alternative that offers a great user experience for all, not just technical users.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bitkit.to/",target:"_blank",rel:"noopener noreferrer"}},[e._v("And that's how Bitkit was born."),t("OutboundLink")],1)]),e._v(" "),t("h1",{attrs:{id:"before-ldk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#before-ldk"}},[e._v("#")]),e._v(" Before LDK")]),e._v(" "),t("p",[e._v("Choosing your tech stack is always challenging. When we first looked into the available Lightning Network implementations, we faced a difficult decision.")]),e._v(" "),t("p",[e._v("Rust-lightning, now known as LDK, had a promising modular architecture but was still in the early stages of development. We considered developing an implementation from scratch to meet Bitkit's specific needs, akin to Acinq's approach with Eclair, but other priorities led us to set this option aside. Ultimately, we adopted LND, the most prevalent implementation at the time. Breez had successfully showcased its potential, making it a logical choice for our stack.")]),e._v(" "),t("p",[e._v("We used LND as the backbone of Bitkit for more than a year, but one aspect stood in the way of providing an optimal user experience: the initialization time. LND utilizes Neutrino, a light Bitcoin client that downloads compact block filters to synchronize with the blockchain. Although it provides better privacy than Electrum Server or Esplora, it's not as fast.")]),e._v(" "),t("p",[e._v("The implications of the initial synchronization time extended well beyond waiting a few seconds. The longer the app stays closed, the longer the synchronization time. We often impatiently closed the app before it finished syncing, causing it to stay out of sync permanently. When we waited for it to fully synchronize, we often found our channel closed, forcing us to start over.")]),e._v(" "),t("p",[e._v("If we were frustrated, Bitkit users would be, too. This reminded us of the second-order effects caused by the technology stacked into our products. John, our CEO, said, “We can’t do this to our users.”")]),e._v(" "),t("p",[e._v("LND was not designed to be modular, making it challenging to swap out Neutrino. To provide the user experience we wanted, we'd need to develop Bitkit on top of a more flexible library. Otherwise, the user experience of self-custodial wallets would continue to fall short, and custodial wallets would remain more popular.")]),e._v(" "),t("p",[e._v("Meanwhile, LDK had come a long way since the early Rust-Lightning days. After revisiting it, its mobile-friendliness convinced us it was the right path forward. The switching cost was high, but we believed our decision would pay off in the long run. So we archived our "),t("a",{attrs:{href:"https://github.com/synonymdev/react-native-lightning",target:"_blank",rel:"noopener noreferrer"}},[e._v("React Native Lightning library"),t("OutboundLink")],1),e._v(" and merged a "),t("a",{attrs:{href:"https://github.com/synonymdev/bitkit/pull/146",target:"_blank",rel:"noopener noreferrer"}},[e._v("pull request"),t("OutboundLink")],1),e._v(", subtracting more than a year of work.")]),e._v(" "),t("p",[e._v("It was time for LDK.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did")]),e._v(" "),t("p",[e._v("Bitkit is built on React Native, and LDK primarily supports Kotlin and Swift bindings. Not to mention, there wasn't an off-the-shelf "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/announcing-ldk-node/",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node"),t("OutboundLink")],1),e._v(" available back then. This led us to develop the "),t("a",{attrs:{href:"https://github.com/synonymdev/react-native-ldk",target:"_blank",rel:"noopener noreferrer"}},[e._v("React Native LDK library"),t("OutboundLink")],1),e._v(" from the ground up, which has since been adopted by "),t("a",{attrs:{href:"https://github.com/EttaWallet/EttaWallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Etta"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://github.com/bennyhodl/baywallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bay"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("By the time we decided to implement LDK, we had already built an on-chain wallet into Bitkit. LDK's flexibility allowed us to preserve it while we focused on rebuilding the Lightning logic.")]),e._v(" "),t("p",[e._v("We've recently "),t("a",{attrs:{href:"https://github.com/synonymdev/bitkit/pull/1450",target:"_blank",rel:"noopener noreferrer"}},[e._v("refactored the on-chain logic out of Bitkit"),t("OutboundLink")],1),e._v(" into a library, and LDK once again made it easy to retain the required methods and pass them through as needed.")]),e._v(" "),t("p",[e._v("We've also developed a custom "),t("a",{attrs:{href:"https://lightningdevkit.org/key_management/",target:"_blank",rel:"noopener noreferrer"}},[e._v("key manager"),t("OutboundLink")],1),e._v(" so the outputs of channel closure transactions get spent directly to Bitkit's on-chain wallet, removing the need for a costly sweeping transaction.")]),e._v(" "),t("p",[e._v("Throughout both on-chain wallet migrations, LDK enabled us to use Electrum Servers as the source of blockchain data, significantly reducing the initial sync time we've previously encountered.")]),e._v(" "),t("p",[e._v("To further minimize initialization delays, we started using LDK's "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/announcing-rapid-gossip-sync/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync"),t("OutboundLink")],1),e._v(". It skips client-side signature verification and compresses graph data, shrinking the required bandwidth and CPU resources. Without RGS, the easiest alternative to achieve fast initialization would be delegating routing to our servers, revealing users' payment destinations. With RGS, pathfinding is fast and client-side, preserving Lightning's privacy properties.")]),e._v(" "),t("p",[e._v("The customizability of the "),t("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/struct.ProbabilisticScorer.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("probabilistic scorer"),t("OutboundLink")],1),e._v(" parameters allowed us to further improve route-finding, translating into a higher payment success rate for users.")]),e._v(" "),t("p",[e._v("In addition, we've architected a custom backup server to meet Bitkit's specific requirements, which LDK was flexible enough to accommodate.")]),e._v(" "),t("figure",[t("img",{attrs:{src:i(347),alt:"Bitkit architecture"}})]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("Migrating to LDK wasn't an easy decision, but time has proven it to be the correct one. The support from the Spiral team was instrumental in easing the migration.")]),e._v(" "),t("p",[e._v("LDK enables us to focus on building a great wallet instead of getting bogged down by the complexities of the Lightning Network protocol.")]),e._v(" "),t("p",[e._v("Ultimately, LDK helps us to narrow the user experience gap between custodial and self-custodial wallets. As long as the lack of options leads people to rely on custodians, LDK will be pivotal in helping us to build a better alternative.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/19.8a6869e1.js b/assets/js/20.e149ffdd.js similarity index 95% rename from assets/js/19.8a6869e1.js rename to assets/js/20.e149ffdd.js index a754b753a..1ddfe3b47 100644 --- a/assets/js/19.8a6869e1.js +++ b/assets/js/20.e149ffdd.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{348:function(e,t,a){e.exports=a.p+"assets/img/cash-app-architecture.b24c7ec1.svg"},385:function(e,t,a){"use strict";a.r(t);var n=a(7),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Cash App allows users to instantly deposit and withdraw bitcoin over the lightning network. As an engineer on the Cash App Lightning Wallet team, I was very involved in the entire implementation process.")]),e._v(" "),t("p",[e._v("Cash App is the #1 Finance App in the app store – we have extremely high standards for product development and the infrastructure that powers all our cool features. We were looking for a solution that would ensure high reliability, high scalability, and a stellar developer experience. Cash App is the financial hub for millions of people and often the first place an individual acquires bitcoin. It’s important to have a slick user experience and robust infrastructure that can onboard many new users. As a publicly traded company we take security seriously and need the ability to customize our wallet implementation in order to adhere to strict standards.")]),e._v(" "),t("p",[e._v("We chose LDK for various reasons over other implementations. It provided us with a lot of customizability and flexibility. The "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected",target:"_blank",rel:"noopener noreferrer"}},[e._v("Java bindings"),t("OutboundLink")],1),e._v(" let us develop in Kotlin, which is the preferred language for backend services. We also have a great working relationship with the "),t("a",{attrs:{href:"https://spiral.xyz/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spiral"),t("OutboundLink")],1),e._v(" folks, making it easy to collaborate on more advanced feature requests such as phantom invoices.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did")]),e._v(" "),t("p",[e._v("LDK allowed us to develop a scalable lightning node infrastructure. Cash App runs multiple wallet nodes and has strict parameters around opening channels and connecting to peers. We have logic that does advanced probing in the background in order to ensure an up-to-date snapshot of liquidity on the lightning network.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(348),alt:"CashApp architecture"}})]),e._v(" "),t("p",[e._v("Probing is done before every send, allowing us to pre-fetch a route and execute the send once the customer confirms. LDK’s "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/introducing-phantom-node-payments/",target:"_blank",rel:"noopener noreferrer"}},[e._v("phantom node"),t("OutboundLink")],1),e._v(" feature makes it possible to generate invoices that can be claimed by more than one node. We use MySQL to save our channel state data + node metadata in order to quickly shut down and start up nodes at will on different servers. Additionally, LDK lets us run AB tests on different pathfinding algorithms.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("LDK made it possible to relatively quickly build an easy-to-use lightning wallet while adhering to the complicated constraints Cash App faces as a publicly traded company with tens of millions of users. Users can now instantly deposit and withdraw bitcoin to Cash App over lightning.")]),e._v(" "),t("p",[e._v("To learn more check out this "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=kbhL5RqL8Aw",target:"_blank",rel:"noopener noreferrer"}},[e._v("presentation"),t("OutboundLink")],1),e._v(" at btc++ explaining some of the trade-offs the Cash App team had to think about when comparing LDK to other solutions.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{352:function(e,t,a){e.exports=a.p+"assets/img/cash-app-architecture.b24c7ec1.svg"},389:function(e,t,a){"use strict";a.r(t);var n=a(7),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Cash App allows users to instantly deposit and withdraw bitcoin over the lightning network. As an engineer on the Cash App Lightning Wallet team, I was very involved in the entire implementation process.")]),e._v(" "),t("p",[e._v("Cash App is the #1 Finance App in the app store – we have extremely high standards for product development and the infrastructure that powers all our cool features. We were looking for a solution that would ensure high reliability, high scalability, and a stellar developer experience. Cash App is the financial hub for millions of people and often the first place an individual acquires bitcoin. It’s important to have a slick user experience and robust infrastructure that can onboard many new users. As a publicly traded company we take security seriously and need the ability to customize our wallet implementation in order to adhere to strict standards.")]),e._v(" "),t("p",[e._v("We chose LDK for various reasons over other implementations. It provided us with a lot of customizability and flexibility. The "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected",target:"_blank",rel:"noopener noreferrer"}},[e._v("Java bindings"),t("OutboundLink")],1),e._v(" let us develop in Kotlin, which is the preferred language for backend services. We also have a great working relationship with the "),t("a",{attrs:{href:"https://spiral.xyz/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spiral"),t("OutboundLink")],1),e._v(" folks, making it easy to collaborate on more advanced feature requests such as phantom invoices.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did")]),e._v(" "),t("p",[e._v("LDK allowed us to develop a scalable lightning node infrastructure. Cash App runs multiple wallet nodes and has strict parameters around opening channels and connecting to peers. We have logic that does advanced probing in the background in order to ensure an up-to-date snapshot of liquidity on the lightning network.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(352),alt:"CashApp architecture"}})]),e._v(" "),t("p",[e._v("Probing is done before every send, allowing us to pre-fetch a route and execute the send once the customer confirms. LDK’s "),t("a",{attrs:{href:"https://lightningdevkit.org/blog/introducing-phantom-node-payments/",target:"_blank",rel:"noopener noreferrer"}},[e._v("phantom node"),t("OutboundLink")],1),e._v(" feature makes it possible to generate invoices that can be claimed by more than one node. We use MySQL to save our channel state data + node metadata in order to quickly shut down and start up nodes at will on different servers. Additionally, LDK lets us run AB tests on different pathfinding algorithms.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("LDK made it possible to relatively quickly build an easy-to-use lightning wallet while adhering to the complicated constraints Cash App faces as a publicly traded company with tens of millions of users. Users can now instantly deposit and withdraw bitcoin to Cash App over lightning.")]),e._v(" "),t("p",[e._v("To learn more check out this "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=kbhL5RqL8Aw",target:"_blank",rel:"noopener noreferrer"}},[e._v("presentation"),t("OutboundLink")],1),e._v(" at btc++ explaining some of the trade-offs the Cash App team had to think about when comparing LDK to other solutions.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/20.5cff8d2a.js b/assets/js/21.4c409f2f.js similarity index 98% rename from assets/js/20.5cff8d2a.js rename to assets/js/21.4c409f2f.js index 860314dec..278437ed4 100644 --- a/assets/js/20.5cff8d2a.js +++ b/assets/js/21.4c409f2f.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{351:function(e,t,a){e.exports=a.p+"assets/img/ldk-roadmap.08c2e5db.png"},388:function(e,t,a){"use strict";a.r(t);var r=a(7),o=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("LDK is going to have a big year. Several key features are actively being developed or expected to be developed in the next few quarters. There are also a few projects of interest that don’t yet have any committed developers. If you want to get involved, hop into the "),t("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discord Server"),t("OutboundLink")],1),e._v(" or "),t("a",{attrs:{href:"https://github.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("GitHub repo"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("As a reminder, the LDK project is community-driven with no centralized authority. Anyone is welcome to contribute and propose ideas at any point. Additionally, it’s extremely important to listen to LDK users. The timeline listed below is just an estimate that may shift if a user request needs to be prioritized over another project.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(351),alt:"OM"}})]),e._v(" "),t("h1",{attrs:{id:"activecommited-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#activecommited-projects"}},[e._v("#")]),e._v(" Active/Commited Projects")]),e._v(" "),t("h2",{attrs:{id:"ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node"}},[e._v("#")]),e._v(" LDK Node")]),e._v(" "),t("p",[e._v("LDK Node is an implementation of an LDK-based LN wallet and node. The LDK API is a powerful, extensive API that gives developers significant control, which can be intimidating to the uninitiated user. The LDK Node project delivers a fully functional LN wallet/node. The mobile-optimized recipe includes a "),t("a",{attrs:{href:"https://bitcoindevkit.org",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v("-based on-chain wallet, integration with Esplora/Electrum for block data, "),t("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/*/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[e._v("RGS"),t("OutboundLink")],1),e._v(" for performant mobile pathfinding, use of SQLite for local data storage, and VSS (once it is ready) for cloud backup of LN and other wallet state. The end result is a very small API surface (~15 methods vs. the >900 methods in LDK API), making it extremely easy to build a functioning mobile wallet in less than a day.")]),e._v(" "),t("p",[e._v("LDK Node can serve a variety of purposes for developers. For starters, it provides a simple way to get a mobile LN node/wallet up and running. Developers are then able to prototype the experience they’re imagining, and in some cases this will be sufficient for them to build and launch their product in production.")]),e._v(" "),t("p",[e._v("In other cases, developers will come to realize more customization is necessary, and they’ll have a couple of options at their disposal:")]),e._v(" "),t("ol",[t("li",[e._v("Build using the lower-level, more powerful LDK API and reference the LDK Node as an example.")]),e._v(" "),t("li",[e._v("Fork the LDK Node code and make custom modifications themselves. This has the benefit of reusing most of the LDK Node code. However, this requires knowledge of Rust and exposing more of the LDK API in LDK Node.")])]),e._v(" "),t("p",[e._v("While LDK Node is written in Rust, it is anticipated many languages will be supported through "),t("a",{attrs:{href:"https://github.com/mozilla/uniffi-rs",target:"_blank",rel:"noopener noreferrer"}},[e._v("UniFFI"),t("OutboundLink")],1),e._v(" or other mechanisms, including:")]),e._v(" "),t("ul",[t("li",[e._v("Java/Kotlin (near term)")]),e._v(" "),t("li",[e._v("Swift (near term)")]),e._v(" "),t("li",[e._v("Python (near term)")]),e._v(" "),t("li",[e._v("Flutter (near term)")]),e._v(" "),t("li",[e._v("React Native (near term)")]),e._v(" "),t("li",[e._v("Web (medium term)")])]),e._v(" "),t("p",[e._v("Through the development of LDK Node, it has been observed that most of the code can also be leveraged for a server configuration. The LDK project is conducting ongoing customer research to identify the needs and requirements for this configuration. The end result might be an LDK Node server daemon with a small RPC API.")]),e._v(" "),t("p",[e._v("The plan is to launch an initial version of LDK Node for mobile in Q2 2023 with continued improvements over time.")]),e._v(" "),t("h2",{attrs:{id:"bolt-12"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bolt-12"}},[e._v("#")]),e._v(" BOLT 12")]),e._v(" "),t("p",[e._v("As of the 114 release, LDK supports onion messages and parsing BOLT 12 messages. It is expected to have full BOLT 12 send/receive support including blinded paths and compatibility with other BOLT 12 implementations in Q2 of 2023.")]),e._v(" "),t("h2",{attrs:{id:"anchor-outputs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#anchor-outputs"}},[e._v("#")]),e._v(" Anchor Outputs")]),e._v(" "),t("p",[e._v("LDK should fully support anchor outputs by Q2 2023.")]),e._v(" "),t("h2",{attrs:{id:"vss"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#vss"}},[e._v("#")]),e._v(" VSS")]),e._v(" "),t("p",[e._v("VSS (Versioned Storage Service) addresses two problems. First, it offers a cloud backup for (encrypted) LN state and other wallet data that is crucial for recovery if the phone is lost or otherwise unavailable. Second, VSS will enable support for multi-device access to the same wallet, handling the synchronization properly so the wallet doesn’t wind up in a confused state. The first phase is expected to be released in Q2 2023. The second phase will be subject to monitoring for demand from wallets and may slip to 2024.")]),e._v(" "),t("h2",{attrs:{id:"improved-async-ness-in-ldk-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#improved-async-ness-in-ldk-api"}},[e._v("#")]),e._v(" Improved Async-ness in LDK API")]),e._v(" "),t("p",[e._v("The Rust language originally did not support async but it was added after the rust-lightning project started. Thus, LDK itself initially only supported synchronous calls, but over time LDK is adding more async support throughout the API.")]),e._v(" "),t("h2",{attrs:{id:"simple-taproot-channels"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#simple-taproot-channels"}},[e._v("#")]),e._v(" Simple Taproot Channels")]),e._v(" "),t("p",[e._v("Work has been ongoing since last fall to add "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/995",target:"_blank",rel:"noopener noreferrer"}},[e._v("simple taproot channels"),t("OutboundLink")],1),e._v(". LDK developers have provided feedback to the Taproot protocol specification which has resulted in improvements, and it is now close to finalizing simple channels. While LDK has its own MuSig implementation for development purposes, the LDK project will wait for the "),t("a",{attrs:{href:"https://github.com/BlockstreamResearch/secp256k1-zkp/pull/211",target:"_blank",rel:"noopener noreferrer"}},[e._v("libsecp implementation"),t("OutboundLink")],1),e._v(" as well as "),t("a",{attrs:{href:"https://github.com/BlockstreamResearch/rust-secp256k1-zkp/pull/48",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust bindings"),t("OutboundLink")],1),e._v(" in order to have the highest security assurances. The hope is that the spec, libsecp, and the LDK implementation all come together for a Q2 2023 release.")]),e._v(" "),t("h2",{attrs:{id:"dual-funded-channels"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#dual-funded-channels"}},[e._v("#")]),e._v(" Dual-Funded Channels")]),e._v(" "),t("p",[e._v("Some work "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/issues/1621",target:"_blank",rel:"noopener noreferrer"}},[e._v("has begun"),t("OutboundLink")],1),e._v(" such as refactoring and implementing the "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/851",target:"_blank",rel:"noopener noreferrer"}},[e._v("interactive tx protocol"),t("OutboundLink")],1),e._v(". Dual-funded channels might make a release in Q2 2023, but more likely Q3 2023.")]),e._v(" "),t("h2",{attrs:{id:"splicing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#splicing"}},[e._v("#")]),e._v(" Splicing")]),e._v(" "),t("p",[e._v("Work has not yet begun on splicing due to other commitments, but several developers have committed to working on it as a next project. Work is expected to commence in Q2. Given work hasn’t started yet, it is hard to estimate completion, but an aim for Q3 2023 seems reasonable at this point.")]),e._v(" "),t("h2",{attrs:{id:"async-payments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#async-payments"}},[e._v("#")]),e._v(" Async Payments")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989#issuecomment-1325389542",target:"_blank",rel:"noopener noreferrer"}},[e._v("async payments proposal"),t("OutboundLink")],1),e._v(" will substantially improve the mobile wallet user experience by allowing people to receive payments under any conditions. The general design and workflow has been "),t("a",{attrs:{href:"https://gist.github.com/remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1",target:"_blank",rel:"noopener noreferrer"}},[e._v("mostly fleshed out"),t("OutboundLink")],1),e._v(". The initial plan is to build a prototype and improve the specification along the way.")]),e._v(" "),t("p",[e._v("The work will be broken down into two phases. The first phase will support async receive and the second will support async send. The reasoning behind this two stage approach is that the first phase has value on its own. Any custodial service, which will naturally have persistent internet, would then be able to reliably send payments to recipients without a persistent internet connection (mobile phones, web browser wallets, etc.).")]),e._v(" "),t("p",[e._v("The second phase is of course necessary for wallets sending from a phone or web browser. This will require support of trampoline in order to retry payments in a trustless way from the sender’s peer (eg an LSP).")]),e._v(" "),t("p",[e._v("LDK is just starting this development, so timeframes have large error bars, but probably the best case scenario would be delivering a working demonstration of phase 1 in Q3 2023 and phase 2 in Q4 2023. In addition to a working demonstration, it is expected to publish a complete specification for each phase that will be available for feedback by the development community.")]),e._v(" "),t("h2",{attrs:{id:"ptlcs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ptlcs"}},[e._v("#")]),e._v(" PTLCs")]),e._v(" "),t("p",[e._v("The LDK project intends to contribute to the specification and development of PTLCs in 2023. The plan is to build upon previous work ("),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003278.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-December/003377.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(") by building a prototype and improving the specification. The ideal outcome is a specification that comes out later this year which gains developer consensus and a complete implementation in LDK. By 2024, hopefully there are multiple implementations and initial deployment throughout the network.")]),e._v(" "),t("h1",{attrs:{id:"prospective-future-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prospective-future-projects"}},[e._v("#")]),e._v(" Prospective Future Projects")]),e._v(" "),t("h2",{attrs:{id:"additional-language-bindings"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#additional-language-bindings"}},[e._v("#")]),e._v(" Additional Language Bindings")]),e._v(" "),t("p",[e._v("LDK already supports many languages, but there are several unsupported languages/frameworks that are used by existing applications, including:")]),e._v(" "),t("ul",[t("li",[e._v("C#")]),e._v(" "),t("li",[e._v("Python")]),e._v(" "),t("li",[e._v("Go")]),e._v(" "),t("li",[e._v("Flutter")])]),e._v(" "),t("h2",{attrs:{id:"custom-scripts"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#custom-scripts"}},[e._v("#")]),e._v(" Custom Scripts")]),e._v(" "),t("p",[e._v("LDK currently only supports the standard LN protocol spec script, however, it is possible to make LDK more flexible and allow 3rd parties to create custom scripts for applications such as taproot, DLCs, or Taro.")]),e._v(" "),t("h2",{attrs:{id:"dynamic-commitments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#dynamic-commitments"}},[e._v("#")]),e._v(" Dynamic Commitments")]),e._v(" "),t("p",[e._v("See "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-March/003531.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("this mailing list post"),t("OutboundLink")],1),e._v(" for reference.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{355:function(e,t,a){e.exports=a.p+"assets/img/ldk-roadmap.08c2e5db.png"},393:function(e,t,a){"use strict";a.r(t);var r=a(7),o=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("LDK is going to have a big year. Several key features are actively being developed or expected to be developed in the next few quarters. There are also a few projects of interest that don’t yet have any committed developers. If you want to get involved, hop into the "),t("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discord Server"),t("OutboundLink")],1),e._v(" or "),t("a",{attrs:{href:"https://github.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("GitHub repo"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("As a reminder, the LDK project is community-driven with no centralized authority. Anyone is welcome to contribute and propose ideas at any point. Additionally, it’s extremely important to listen to LDK users. The timeline listed below is just an estimate that may shift if a user request needs to be prioritized over another project.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(355),alt:"OM"}})]),e._v(" "),t("h1",{attrs:{id:"activecommited-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#activecommited-projects"}},[e._v("#")]),e._v(" Active/Commited Projects")]),e._v(" "),t("h2",{attrs:{id:"ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node"}},[e._v("#")]),e._v(" LDK Node")]),e._v(" "),t("p",[e._v("LDK Node is an implementation of an LDK-based LN wallet and node. The LDK API is a powerful, extensive API that gives developers significant control, which can be intimidating to the uninitiated user. The LDK Node project delivers a fully functional LN wallet/node. The mobile-optimized recipe includes a "),t("a",{attrs:{href:"https://bitcoindevkit.org",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v("-based on-chain wallet, integration with Esplora/Electrum for block data, "),t("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/*/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[e._v("RGS"),t("OutboundLink")],1),e._v(" for performant mobile pathfinding, use of SQLite for local data storage, and VSS (once it is ready) for cloud backup of LN and other wallet state. The end result is a very small API surface (~15 methods vs. the >900 methods in LDK API), making it extremely easy to build a functioning mobile wallet in less than a day.")]),e._v(" "),t("p",[e._v("LDK Node can serve a variety of purposes for developers. For starters, it provides a simple way to get a mobile LN node/wallet up and running. Developers are then able to prototype the experience they’re imagining, and in some cases this will be sufficient for them to build and launch their product in production.")]),e._v(" "),t("p",[e._v("In other cases, developers will come to realize more customization is necessary, and they’ll have a couple of options at their disposal:")]),e._v(" "),t("ol",[t("li",[e._v("Build using the lower-level, more powerful LDK API and reference the LDK Node as an example.")]),e._v(" "),t("li",[e._v("Fork the LDK Node code and make custom modifications themselves. This has the benefit of reusing most of the LDK Node code. However, this requires knowledge of Rust and exposing more of the LDK API in LDK Node.")])]),e._v(" "),t("p",[e._v("While LDK Node is written in Rust, it is anticipated many languages will be supported through "),t("a",{attrs:{href:"https://github.com/mozilla/uniffi-rs",target:"_blank",rel:"noopener noreferrer"}},[e._v("UniFFI"),t("OutboundLink")],1),e._v(" or other mechanisms, including:")]),e._v(" "),t("ul",[t("li",[e._v("Java/Kotlin (near term)")]),e._v(" "),t("li",[e._v("Swift (near term)")]),e._v(" "),t("li",[e._v("Python (near term)")]),e._v(" "),t("li",[e._v("Flutter (near term)")]),e._v(" "),t("li",[e._v("React Native (near term)")]),e._v(" "),t("li",[e._v("Web (medium term)")])]),e._v(" "),t("p",[e._v("Through the development of LDK Node, it has been observed that most of the code can also be leveraged for a server configuration. The LDK project is conducting ongoing customer research to identify the needs and requirements for this configuration. The end result might be an LDK Node server daemon with a small RPC API.")]),e._v(" "),t("p",[e._v("The plan is to launch an initial version of LDK Node for mobile in Q2 2023 with continued improvements over time.")]),e._v(" "),t("h2",{attrs:{id:"bolt-12"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bolt-12"}},[e._v("#")]),e._v(" BOLT 12")]),e._v(" "),t("p",[e._v("As of the 114 release, LDK supports onion messages and parsing BOLT 12 messages. It is expected to have full BOLT 12 send/receive support including blinded paths and compatibility with other BOLT 12 implementations in Q2 of 2023.")]),e._v(" "),t("h2",{attrs:{id:"anchor-outputs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#anchor-outputs"}},[e._v("#")]),e._v(" Anchor Outputs")]),e._v(" "),t("p",[e._v("LDK should fully support anchor outputs by Q2 2023.")]),e._v(" "),t("h2",{attrs:{id:"vss"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#vss"}},[e._v("#")]),e._v(" VSS")]),e._v(" "),t("p",[e._v("VSS (Versioned Storage Service) addresses two problems. First, it offers a cloud backup for (encrypted) LN state and other wallet data that is crucial for recovery if the phone is lost or otherwise unavailable. Second, VSS will enable support for multi-device access to the same wallet, handling the synchronization properly so the wallet doesn’t wind up in a confused state. The first phase is expected to be released in Q2 2023. The second phase will be subject to monitoring for demand from wallets and may slip to 2024.")]),e._v(" "),t("h2",{attrs:{id:"improved-async-ness-in-ldk-api"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#improved-async-ness-in-ldk-api"}},[e._v("#")]),e._v(" Improved Async-ness in LDK API")]),e._v(" "),t("p",[e._v("The Rust language originally did not support async but it was added after the rust-lightning project started. Thus, LDK itself initially only supported synchronous calls, but over time LDK is adding more async support throughout the API.")]),e._v(" "),t("h2",{attrs:{id:"simple-taproot-channels"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#simple-taproot-channels"}},[e._v("#")]),e._v(" Simple Taproot Channels")]),e._v(" "),t("p",[e._v("Work has been ongoing since last fall to add "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/995",target:"_blank",rel:"noopener noreferrer"}},[e._v("simple taproot channels"),t("OutboundLink")],1),e._v(". LDK developers have provided feedback to the Taproot protocol specification which has resulted in improvements, and it is now close to finalizing simple channels. While LDK has its own MuSig implementation for development purposes, the LDK project will wait for the "),t("a",{attrs:{href:"https://github.com/BlockstreamResearch/secp256k1-zkp/pull/211",target:"_blank",rel:"noopener noreferrer"}},[e._v("libsecp implementation"),t("OutboundLink")],1),e._v(" as well as "),t("a",{attrs:{href:"https://github.com/BlockstreamResearch/rust-secp256k1-zkp/pull/48",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust bindings"),t("OutboundLink")],1),e._v(" in order to have the highest security assurances. The hope is that the spec, libsecp, and the LDK implementation all come together for a Q2 2023 release.")]),e._v(" "),t("h2",{attrs:{id:"dual-funded-channels"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#dual-funded-channels"}},[e._v("#")]),e._v(" Dual-Funded Channels")]),e._v(" "),t("p",[e._v("Some work "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/issues/1621",target:"_blank",rel:"noopener noreferrer"}},[e._v("has begun"),t("OutboundLink")],1),e._v(" such as refactoring and implementing the "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/851",target:"_blank",rel:"noopener noreferrer"}},[e._v("interactive tx protocol"),t("OutboundLink")],1),e._v(". Dual-funded channels might make a release in Q2 2023, but more likely Q3 2023.")]),e._v(" "),t("h2",{attrs:{id:"splicing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#splicing"}},[e._v("#")]),e._v(" Splicing")]),e._v(" "),t("p",[e._v("Work has not yet begun on splicing due to other commitments, but several developers have committed to working on it as a next project. Work is expected to commence in Q2. Given work hasn’t started yet, it is hard to estimate completion, but an aim for Q3 2023 seems reasonable at this point.")]),e._v(" "),t("h2",{attrs:{id:"async-payments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#async-payments"}},[e._v("#")]),e._v(" Async Payments")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989#issuecomment-1325389542",target:"_blank",rel:"noopener noreferrer"}},[e._v("async payments proposal"),t("OutboundLink")],1),e._v(" will substantially improve the mobile wallet user experience by allowing people to receive payments under any conditions. The general design and workflow has been "),t("a",{attrs:{href:"https://gist.github.com/remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1",target:"_blank",rel:"noopener noreferrer"}},[e._v("mostly fleshed out"),t("OutboundLink")],1),e._v(". The initial plan is to build a prototype and improve the specification along the way.")]),e._v(" "),t("p",[e._v("The work will be broken down into two phases. The first phase will support async receive and the second will support async send. The reasoning behind this two stage approach is that the first phase has value on its own. Any custodial service, which will naturally have persistent internet, would then be able to reliably send payments to recipients without a persistent internet connection (mobile phones, web browser wallets, etc.).")]),e._v(" "),t("p",[e._v("The second phase is of course necessary for wallets sending from a phone or web browser. This will require support of trampoline in order to retry payments in a trustless way from the sender’s peer (eg an LSP).")]),e._v(" "),t("p",[e._v("LDK is just starting this development, so timeframes have large error bars, but probably the best case scenario would be delivering a working demonstration of phase 1 in Q3 2023 and phase 2 in Q4 2023. In addition to a working demonstration, it is expected to publish a complete specification for each phase that will be available for feedback by the development community.")]),e._v(" "),t("h2",{attrs:{id:"ptlcs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ptlcs"}},[e._v("#")]),e._v(" PTLCs")]),e._v(" "),t("p",[e._v("The LDK project intends to contribute to the specification and development of PTLCs in 2023. The plan is to build upon previous work ("),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003278.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-December/003377.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(") by building a prototype and improving the specification. The ideal outcome is a specification that comes out later this year which gains developer consensus and a complete implementation in LDK. By 2024, hopefully there are multiple implementations and initial deployment throughout the network.")]),e._v(" "),t("h1",{attrs:{id:"prospective-future-projects"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prospective-future-projects"}},[e._v("#")]),e._v(" Prospective Future Projects")]),e._v(" "),t("h2",{attrs:{id:"additional-language-bindings"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#additional-language-bindings"}},[e._v("#")]),e._v(" Additional Language Bindings")]),e._v(" "),t("p",[e._v("LDK already supports many languages, but there are several unsupported languages/frameworks that are used by existing applications, including:")]),e._v(" "),t("ul",[t("li",[e._v("C#")]),e._v(" "),t("li",[e._v("Python")]),e._v(" "),t("li",[e._v("Go")]),e._v(" "),t("li",[e._v("Flutter")])]),e._v(" "),t("h2",{attrs:{id:"custom-scripts"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#custom-scripts"}},[e._v("#")]),e._v(" Custom Scripts")]),e._v(" "),t("p",[e._v("LDK currently only supports the standard LN protocol spec script, however, it is possible to make LDK more flexible and allow 3rd parties to create custom scripts for applications such as taproot, DLCs, or Taro.")]),e._v(" "),t("h2",{attrs:{id:"dynamic-commitments"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#dynamic-commitments"}},[e._v("#")]),e._v(" Dynamic Commitments")]),e._v(" "),t("p",[e._v("See "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2022-March/003531.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("this mailing list post"),t("OutboundLink")],1),e._v(" for reference.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/21.321bf3e6.js b/assets/js/22.b180a053.js similarity index 93% rename from assets/js/21.321bf3e6.js rename to assets/js/22.b180a053.js index b43a1239a..f6e702869 100644 --- a/assets/js/21.321bf3e6.js +++ b/assets/js/22.b180a053.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{356:function(e,n,t){e.exports=t.p+"assets/img/sensei-architecture.0959f7aa.svg"},391:function(e,n,t){"use strict";t.r(n);var a=t(7),i=Object(a.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("p",[n("a",{attrs:{href:"https://l2.technology/sensei",target:"_blank",rel:"noopener noreferrer"}},[e._v("Sensei"),n("OutboundLink")],1),e._v(" is a lightning node application optimized to serve many nodes within a single instance. It offers a beautiful web interface for admins to manage nodes as well as an interface for individual nodes to perform all of the common lightning network tasks such as connecting to peers, opening and closing channels, and creating and paying invoices. Sensei exposes http and grpc interfaces, allowing automation and programmatic control of the nodes.")]),e._v(" "),n("p",[e._v("One goal of the project was to design an application that could make running multiple lightning nodes as lightweight as possible in terms of resource utilization. Sensei needed a lightning implementation that was designed for low-resource environments and could enable sharing of specific components across a set of nodes.")]),e._v(" "),n("h1",{attrs:{id:"what-we-did"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),n("p",[e._v("LDK’s flexibility was the main reason I chose LDK as Sensei’s lightning implementation over other options. I really needed a way for all of the nodes to share certain components (block data, network graph message handling, pathfinding, etc) and LDK allowed this functionality out of the box.")]),e._v(" "),n("figure",[n("img",{attrs:{src:t(356),alt:"Sensei architecture"}})]),e._v(" "),n("p",[e._v("To do something similar with the other implementations would have required maintaining project forks or running multiple instances of the full daemons. The former creates never-ending maintenance work and the latter could never achieve the desired performance characteristics.")]),e._v(" "),n("h1",{attrs:{id:"results"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),n("p",[e._v("LDK allowed a one-person development team to produce a standalone lightning node server with unique functionality. I was able to piece together the underlying lightning components exactly how I needed without having to maintain forks containing ugly hacks or be limited by the resource utilization of an existing daemon. LDK handles all of the low-level lightning network protocol details, which frees up my time to focus on Sensei’s core features. It’s still early days for Sensei but I’m already able to use it to run hundreds of lightning nodes on my laptop!")])])}),[],!1,null,null,null);n.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{360:function(e,n,t){e.exports=t.p+"assets/img/sensei-architecture.0959f7aa.svg"},396:function(e,n,t){"use strict";t.r(n);var a=t(7),i=Object(a.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("p",[n("a",{attrs:{href:"https://l2.technology/sensei",target:"_blank",rel:"noopener noreferrer"}},[e._v("Sensei"),n("OutboundLink")],1),e._v(" is a lightning node application optimized to serve many nodes within a single instance. It offers a beautiful web interface for admins to manage nodes as well as an interface for individual nodes to perform all of the common lightning network tasks such as connecting to peers, opening and closing channels, and creating and paying invoices. Sensei exposes http and grpc interfaces, allowing automation and programmatic control of the nodes.")]),e._v(" "),n("p",[e._v("One goal of the project was to design an application that could make running multiple lightning nodes as lightweight as possible in terms of resource utilization. Sensei needed a lightning implementation that was designed for low-resource environments and could enable sharing of specific components across a set of nodes.")]),e._v(" "),n("h1",{attrs:{id:"what-we-did"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),n("p",[e._v("LDK’s flexibility was the main reason I chose LDK as Sensei’s lightning implementation over other options. I really needed a way for all of the nodes to share certain components (block data, network graph message handling, pathfinding, etc) and LDK allowed this functionality out of the box.")]),e._v(" "),n("figure",[n("img",{attrs:{src:t(360),alt:"Sensei architecture"}})]),e._v(" "),n("p",[e._v("To do something similar with the other implementations would have required maintaining project forks or running multiple instances of the full daemons. The former creates never-ending maintenance work and the latter could never achieve the desired performance characteristics.")]),e._v(" "),n("h1",{attrs:{id:"results"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),n("p",[e._v("LDK allowed a one-person development team to produce a standalone lightning node server with unique functionality. I was able to piece together the underlying lightning components exactly how I needed without having to maintain forks containing ugly hacks or be limited by the resource utilization of an existing daemon. LDK handles all of the low-level lightning network protocol details, which frees up my time to focus on Sensei’s core features. It’s still early days for Sensei but I’m already able to use it to run hundreds of lightning nodes on my laptop!")])])}),[],!1,null,null,null);n.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/22.e4d037c8.js b/assets/js/23.60e41ae2.js similarity index 95% rename from assets/js/22.e4d037c8.js rename to assets/js/23.60e41ae2.js index 58fb226e2..7928dcb63 100644 --- a/assets/js/22.e4d037c8.js +++ b/assets/js/23.60e41ae2.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{357:function(e,t,a){e.exports=a.p+"assets/img/teos-architecture-diagram.3ab57d46.png"},392:function(e,t,a){"use strict";a.r(t);var n=a(7),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[t("a",{attrs:{href:"https://github.com/talaia-labs/rust-teos",target:"_blank",rel:"noopener noreferrer"}},[e._v("The Eye of Satoshi (TEOS)"),t("OutboundLink")],1),e._v(" is a bitcoin watchtower with a specific focus on lightning. Watchtowers are third-party viewing services that help prevent people from cheating on the lightning network by constantly monitoring the bitcoin blockchain for channel breaches. If found, a watchtower will react by penalizing the misbehaving party and sending all funds to its counterpart.")]),e._v(" "),t("p",[e._v("In order for TEOS to work, information is needed from several different building blocks. This includes block data processing (such as reacting to forks/chain splits), interaction with a bitcoin node (for transaction broadcasting), and general tooling around bitcoin/lightning (transaction parsing, data encoding/decoding, lightning P2P messaging, etc).")]),e._v(" "),t("p",[e._v("TEOS does not have strong performance requirements, as data is checked in newly processed blocks approximately every 10 mins. However, if it services a substantial amount of nodes at once or channels with high traffic, it may need to compare processed info against huge amounts of data.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),t("p",[e._v("We initially had a Python implementation, but as the project evolved we realized it could be beneficial to switch to a language that was more robust and had better tooling. Rust was an obvious choice given how well it works for other bitcoin-related projects. Moving away from Python allowed us to drop a substantial amount of dependencies that were unmaintained or maintained by us, and instead use properly maintained counterparts.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(357),alt:"TEOS architecture"}})]),e._v(" "),t("p",[e._v("While it did take time to perform the Rust re-implementation, it was worth it for several reasons. LDK does a substantial amount of the low-level heavy lifting (e.g. reorg management), allowing us to remove several components of the original design and abstract interaction with bitcoind. Additionally, Python lacks proper support for most of lightning’s functionality, so we would have had to implement and maintain all of the related toolings to support lightning P2P communication features.")]),e._v(" "),t("p",[e._v("Furthermore, LDK supports various lightning features that we may need in the future, such as anchors. At the end of the day, LDK makes it possible to focus on the product/protocol you are building and care less about the low-level lightning/bitcoin parts that are needed.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("The TEOS codebase is now more robust and stable, making it easier to contribute to and integrate with other projects.")]),e._v(" "),t("p",[e._v("In terms of functionality, we recently reached the same state as the old Python codebase. We are currently focusing on new features and integrations. Additionally, using Rust and LDK has allowed us to build a healthier community. It’s easier to make improvements to a project when you use the same tools and literally speak the same language.")]),e._v(" "),t("p",[e._v("It's been a pleasure working with the LDK team. They’ve helped us solve several Rust and LDK issues, and have been open to accepting PRs and implementing new functionality that we require.")]),e._v(" "),t("p",[e._v("Learn how you can deploy your own TEOS watchtower on the Bitcoin Developers Youtube "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=8vzNB_NZt2A",target:"_blank",rel:"noopener noreferrer"}},[e._v("channel"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{361:function(e,t,a){e.exports=a.p+"assets/img/teos-architecture-diagram.3ab57d46.png"},397:function(e,t,a){"use strict";a.r(t);var n=a(7),o=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[t("a",{attrs:{href:"https://github.com/talaia-labs/rust-teos",target:"_blank",rel:"noopener noreferrer"}},[e._v("The Eye of Satoshi (TEOS)"),t("OutboundLink")],1),e._v(" is a bitcoin watchtower with a specific focus on lightning. Watchtowers are third-party viewing services that help prevent people from cheating on the lightning network by constantly monitoring the bitcoin blockchain for channel breaches. If found, a watchtower will react by penalizing the misbehaving party and sending all funds to its counterpart.")]),e._v(" "),t("p",[e._v("In order for TEOS to work, information is needed from several different building blocks. This includes block data processing (such as reacting to forks/chain splits), interaction with a bitcoin node (for transaction broadcasting), and general tooling around bitcoin/lightning (transaction parsing, data encoding/decoding, lightning P2P messaging, etc).")]),e._v(" "),t("p",[e._v("TEOS does not have strong performance requirements, as data is checked in newly processed blocks approximately every 10 mins. However, if it services a substantial amount of nodes at once or channels with high traffic, it may need to compare processed info against huge amounts of data.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),t("p",[e._v("We initially had a Python implementation, but as the project evolved we realized it could be beneficial to switch to a language that was more robust and had better tooling. Rust was an obvious choice given how well it works for other bitcoin-related projects. Moving away from Python allowed us to drop a substantial amount of dependencies that were unmaintained or maintained by us, and instead use properly maintained counterparts.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(361),alt:"TEOS architecture"}})]),e._v(" "),t("p",[e._v("While it did take time to perform the Rust re-implementation, it was worth it for several reasons. LDK does a substantial amount of the low-level heavy lifting (e.g. reorg management), allowing us to remove several components of the original design and abstract interaction with bitcoind. Additionally, Python lacks proper support for most of lightning’s functionality, so we would have had to implement and maintain all of the related toolings to support lightning P2P communication features.")]),e._v(" "),t("p",[e._v("Furthermore, LDK supports various lightning features that we may need in the future, such as anchors. At the end of the day, LDK makes it possible to focus on the product/protocol you are building and care less about the low-level lightning/bitcoin parts that are needed.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("The TEOS codebase is now more robust and stable, making it easier to contribute to and integrate with other projects.")]),e._v(" "),t("p",[e._v("In terms of functionality, we recently reached the same state as the old Python codebase. We are currently focusing on new features and integrations. Additionally, using Rust and LDK has allowed us to build a healthier community. It’s easier to make improvements to a project when you use the same tools and literally speak the same language.")]),e._v(" "),t("p",[e._v("It's been a pleasure working with the LDK team. They’ve helped us solve several Rust and LDK issues, and have been open to accepting PRs and implementing new functionality that we require.")]),e._v(" "),t("p",[e._v("Learn how you can deploy your own TEOS watchtower on the Bitcoin Developers Youtube "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=8vzNB_NZt2A",target:"_blank",rel:"noopener noreferrer"}},[e._v("channel"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/23.1f8ab982.js b/assets/js/24.34674e30.js similarity index 89% rename from assets/js/23.1f8ab982.js rename to assets/js/24.34674e30.js index 9bdc93d05..b669a6e8c 100644 --- a/assets/js/23.1f8ab982.js +++ b/assets/js/24.34674e30.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{358:function(n,e,t){n.exports=t.p+"assets/img/ldk-block-processing.da054b79.svg"},400:function(n,e,t){"use strict";t.r(e);var o=t(7),a=Object(o.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[n._v("#")]),n._v(" Introduction")]),n._v(" "),e("p",[n._v("In this guide, we'll explore how to provide chain data to LDK upon startup and\nas new blocks are mined. This allows LDK to maintain channel state and monitor\nfor on-chain channel activity.")]),n._v(" "),e("p",[n._v("LDK maintains channels with your node's peers during the course of node\noperation. When a new channel is opened, the "),e("code",[n._v("ChannelManager")]),n._v(" will keep track of\nthe channel's state and tell the "),e("code",[n._v("ChainMonitor")]),n._v(" that a new channel should be\nwatched. The "),e("code",[n._v("ChainMonitor")]),n._v(" does so by maintaining a "),e("code",[n._v("ChannelMonitor")]),n._v(" for each\nchannel.")]),n._v(" "),e("p",[n._v("When a new block is mined, it is connected to the chain while other blocks may\nbe disconnected if reorganized out. Transactions are confirmed or unconfirmed\nduring this process. You are required to feed this activity to LDK which will\nprocess it by:")]),n._v(" "),e("ul",[e("li",[n._v("Updating channel state")]),n._v(" "),e("li",[n._v("Signaling back transactions to filter")]),n._v(" "),e("li",[n._v("Broadcasting transactions if necessary")])]),n._v(" "),e("p",[n._v("We will walk through this process as depicted here:")]),n._v(" "),e("figure",[e("img",{attrs:{src:t(358),alt:"LDK block processing"}})])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{362:function(n,e,t){n.exports=t.p+"assets/img/ldk-block-processing.da054b79.svg"},405:function(n,e,t){"use strict";t.r(e);var o=t(7),a=Object(o.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[n._v("#")]),n._v(" Introduction")]),n._v(" "),e("p",[n._v("In this guide, we'll explore how to provide chain data to LDK upon startup and\nas new blocks are mined. This allows LDK to maintain channel state and monitor\nfor on-chain channel activity.")]),n._v(" "),e("p",[n._v("LDK maintains channels with your node's peers during the course of node\noperation. When a new channel is opened, the "),e("code",[n._v("ChannelManager")]),n._v(" will keep track of\nthe channel's state and tell the "),e("code",[n._v("ChainMonitor")]),n._v(" that a new channel should be\nwatched. The "),e("code",[n._v("ChainMonitor")]),n._v(" does so by maintaining a "),e("code",[n._v("ChannelMonitor")]),n._v(" for each\nchannel.")]),n._v(" "),e("p",[n._v("When a new block is mined, it is connected to the chain while other blocks may\nbe disconnected if reorganized out. Transactions are confirmed or unconfirmed\nduring this process. You are required to feed this activity to LDK which will\nprocess it by:")]),n._v(" "),e("ul",[e("li",[n._v("Updating channel state")]),n._v(" "),e("li",[n._v("Signaling back transactions to filter")]),n._v(" "),e("li",[n._v("Broadcasting transactions if necessary")])]),n._v(" "),e("p",[n._v("We will walk through this process as depicted here:")]),n._v(" "),e("figure",[e("img",{attrs:{src:t(362),alt:"LDK block processing"}})])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/24.217a5514.js b/assets/js/25.b172cf39.js similarity index 89% rename from assets/js/24.217a5514.js rename to assets/js/25.b172cf39.js index e7fa98c34..2cf3c8f90 100644 --- a/assets/js/24.217a5514.js +++ b/assets/js/25.b172cf39.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{359:function(t,e,a){t.exports=a.p+"assets/img/ldk-architecture.c9d2bfc6.svg"},416:function(t,e,a){"use strict";a.r(e);var o=a(7),i=Object(o.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"architecture"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#architecture"}},[t._v("#")]),t._v(" Architecture")]),t._v(" "),e("figure",[e("img",{attrs:{src:a(359),alt:"Architecture"}})]),t._v(" "),e("p",[t._v("Firstly, LDK is not a daemon, but rather its own implementation of the Lightning protocol written as an SDK and designed to be compiled and executed in your application.")]),t._v(" "),e("p",[t._v("This makes it environment agnostic, allowing you to choose your own data storage, wallet, networking stack and blockchain monitoring. In the diagram above the boxes with dotted borders are LDK's modules — these must be configured with either default or custom implementations that you provide.")]),t._v(" "),e("p",[t._v("LDK also uses an event-driven architecture which allows for asynchronous result notification. For example you perform actions like making payments without waiting for the result and are later made aware via an event if the payment was successful or not.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Language Bindings")]),t._v(" "),e("p",[t._v("Although the core SDK is written in Rust, LDK supports many other programming languages. These include Java/Kotlin, Swift, JavaScript/TypeScript (Beta), C++ (Alpha). Check out "),e("RouterLink",{attrs:{to:"/examples/"}},[t._v("examples")]),t._v(" to see some of the implementations out in the wild!")],1)])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{367:function(t,e,a){t.exports=a.p+"assets/img/ldk-architecture.c9d2bfc6.svg"},422:function(t,e,a){"use strict";a.r(e);var o=a(7),i=Object(o.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"architecture"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#architecture"}},[t._v("#")]),t._v(" Architecture")]),t._v(" "),e("figure",[e("img",{attrs:{src:a(367),alt:"Architecture"}})]),t._v(" "),e("p",[t._v("Firstly, LDK is not a daemon, but rather its own implementation of the Lightning protocol written as an SDK and designed to be compiled and executed in your application.")]),t._v(" "),e("p",[t._v("This makes it environment agnostic, allowing you to choose your own data storage, wallet, networking stack and blockchain monitoring. In the diagram above the boxes with dotted borders are LDK's modules — these must be configured with either default or custom implementations that you provide.")]),t._v(" "),e("p",[t._v("LDK also uses an event-driven architecture which allows for asynchronous result notification. For example you perform actions like making payments without waiting for the result and are later made aware via an event if the payment was successful or not.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Language Bindings")]),t._v(" "),e("p",[t._v("Although the core SDK is written in Rust, LDK supports many other programming languages. These include Java/Kotlin, Swift, JavaScript/TypeScript (Beta), C++ (Alpha). Check out "),e("RouterLink",{attrs:{to:"/examples/"}},[t._v("examples")]),t._v(" to see some of the implementations out in the wild!")],1)])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/25.1a47bbb8.js b/assets/js/26.dcd3084f.js similarity index 93% rename from assets/js/25.1a47bbb8.js rename to assets/js/26.dcd3084f.js index 1eec65750..6a4d5eb65 100644 --- a/assets/js/25.1a47bbb8.js +++ b/assets/js/26.dcd3084f.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{364:function(e,n,t){e.exports=t.p+"assets/img/ldk-peer-management.ac42ca47.svg"},422:function(e,n,t){"use strict";t.r(n);var r=t(7),o=Object(r.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"peer-management"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#peer-management"}},[e._v("#")]),e._v(" Peer Management")]),e._v(" "),n("figure",[n("img",{attrs:{src:t(364),alt:"Peer Management"}})]),e._v(" "),n("p",[e._v("One of the first things you'll need to do when building your own Lightning node is connect to a peer. In LDK this is handled by the "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("PeerManager")]),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("PeerManager")]),e._v(" has two dependencies:")]),e._v(" "),n("ul",[n("li",[e._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("ChannelManager")]),n("OutboundLink")],1),e._v(" that enables it to notify peers when it wants to do things such as open channels.")]),e._v(" "),n("li",[e._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.P2PGossipSync.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("P2PGossipSync")]),n("OutboundLink")],1),e._v(" that understands when peers you are connected to send you gossip messages, enables you to forward messages, announce channel opens and more.")])]),e._v(" "),n("p",[e._v("Since LDK knows nothing about your networking stack, you'll need to implement your own networking logic in order to connect to peers on the network. Provide LDK with raw TCP/IP socket data and the library will handle the rest for you.")]),e._v(" "),n("p",[e._v("LDK also handles a number of background tasks that need to happen periodically via "),n("a",{attrs:{href:"https://docs.rs/lightning-background-processor/*/lightning_background_processor/struct.BackgroundProcessor.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("BackgroundProcessor")]),n("OutboundLink")],1)]),e._v(" "),n("div",{staticClass:"custom-block tip"},[n("p",{staticClass:"custom-block-title"},[e._v("Default Implementation")]),e._v(" "),n("p",[e._v("If you are developing in a Rust "),n("a",{attrs:{href:"https://tokio.rs/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Tokio"),n("OutboundLink")],1),e._v(" environment, LDK ships with a socket handling "),n("a",{attrs:{href:"https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/",target:"_blank",rel:"noopener noreferrer"}},[e._v("crate"),n("OutboundLink")],1),e._v(" that let's you easily create new connections with peers.")])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{368:function(e,n,t){e.exports=t.p+"assets/img/ldk-peer-management.ac42ca47.svg"},427:function(e,n,t){"use strict";t.r(n);var r=t(7),o=Object(r.a)({},(function(){var e=this,n=e._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"peer-management"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#peer-management"}},[e._v("#")]),e._v(" Peer Management")]),e._v(" "),n("figure",[n("img",{attrs:{src:t(368),alt:"Peer Management"}})]),e._v(" "),n("p",[e._v("One of the first things you'll need to do when building your own Lightning node is connect to a peer. In LDK this is handled by the "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("PeerManager")]),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("PeerManager")]),e._v(" has two dependencies:")]),e._v(" "),n("ul",[n("li",[e._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("ChannelManager")]),n("OutboundLink")],1),e._v(" that enables it to notify peers when it wants to do things such as open channels.")]),e._v(" "),n("li",[e._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.P2PGossipSync.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("P2PGossipSync")]),n("OutboundLink")],1),e._v(" that understands when peers you are connected to send you gossip messages, enables you to forward messages, announce channel opens and more.")])]),e._v(" "),n("p",[e._v("Since LDK knows nothing about your networking stack, you'll need to implement your own networking logic in order to connect to peers on the network. Provide LDK with raw TCP/IP socket data and the library will handle the rest for you.")]),e._v(" "),n("p",[e._v("LDK also handles a number of background tasks that need to happen periodically via "),n("a",{attrs:{href:"https://docs.rs/lightning-background-processor/*/lightning_background_processor/struct.BackgroundProcessor.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[e._v("BackgroundProcessor")]),n("OutboundLink")],1)]),e._v(" "),n("div",{staticClass:"custom-block tip"},[n("p",{staticClass:"custom-block-title"},[e._v("Default Implementation")]),e._v(" "),n("p",[e._v("If you are developing in a Rust "),n("a",{attrs:{href:"https://tokio.rs/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Tokio"),n("OutboundLink")],1),e._v(" environment, LDK ships with a socket handling "),n("a",{attrs:{href:"https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/",target:"_blank",rel:"noopener noreferrer"}},[e._v("crate"),n("OutboundLink")],1),e._v(" that let's you easily create new connections with peers.")])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/26.a5e25a79.js b/assets/js/27.eb30a5d4.js similarity index 91% rename from assets/js/26.a5e25a79.js rename to assets/js/27.eb30a5d4.js index 2b294548a..bb89e0e73 100644 --- a/assets/js/26.a5e25a79.js +++ b/assets/js/27.eb30a5d4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{373:function(t,e,o){"use strict";o.r(e);var s=o(259);const n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."];var a={name:"NotFound",components:{LayoutWrap:s.a},methods:{getMsg:()=>n[Math.floor(Math.random()*n.length)]}},h=o(7),i=Object(h.a)(a,(function(){var t=this._self._c;return t("LayoutWrap",[t("main",{staticClass:"page"},[t("div",{staticClass:"theme-default-content"},[t("h1",[this._v("404 - Not Found")]),this._v(" "),t("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),t("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{377:function(t,e,o){"use strict";o.r(e);var s=o(259);const n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."];var a={name:"NotFound",components:{LayoutWrap:s.a},methods:{getMsg:()=>n[Math.floor(Math.random()*n.length)]}},h=o(7),i=Object(h.a)(a,(function(){var t=this._self._c;return t("LayoutWrap",[t("main",{staticClass:"page"},[t("div",{staticClass:"theme-default-content"},[t("h1",[this._v("404 - Not Found")]),this._v(" "),t("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),t("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/27.4d29965e.js b/assets/js/28.7cbc9f1a.js similarity index 96% rename from assets/js/27.4d29965e.js rename to assets/js/28.7cbc9f1a.js index 180d705b9..43784ad98 100644 --- a/assets/js/27.4d29965e.js +++ b/assets/js/28.7cbc9f1a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{380:function(e,t,a){"use strict";a.r(t);a(109);var s={props:{name:{type:String,default:"default"},isolated:{type:Boolean,default:!1},languages:{type:Object,required:!1}},data(){return{selectedLanguage:this.languages?Object.keys(this.languages)[0]:null,actualLanguages:this.languages}},computed:{root(){let e,t=this;for(;e=t.$parent;)t=e;return t},localStorageKey(){return"vuepress-plugin-code-switcher@"+this.name}},methods:{switchLanguage(e){if(this.isolated)return this.selectedLanguage=e;"undefined"!=typeof localStorage&&localStorage.setItem(this.localStorageKey,e),this.root.$emit("change",{name:this.name,value:e})},setConfiguredDefaultLanguages(){if(this.languages)return;const e=this.$page.codeSwitcherOptions;e&&e.groups&&e.groups[this.name]&&(this.actualLanguages=e.groups[this.name],this.selectedLanguage=Object.keys(this.actualLanguages)[0])}},created(){if(!this.isolated){if(this.setConfiguredDefaultLanguages(),!this.actualLanguages)throw new Error('You must specify either the "languages" prop or use the "groups" option when configuring the plugin.');if("undefined"!=typeof localStorage){let e=localStorage.getItem(this.localStorageKey);e&&-1!==Object.keys(this.actualLanguages).indexOf(e)&&(this.selectedLanguage=e)}this.root.$on("change",({name:e,value:t})=>{e===this.name&&(this.selectedLanguage=t)})}}},n=a(7),u=Object(n.a)(s,(function(){var e=this,t=e._self._c;return t("div",{staticClass:"code-switcher"},[t("div",{staticClass:"tab-header"},[t("ul",e._l(e.actualLanguages,(function(a,s){return t("li",{key:s,class:{active:e.selectedLanguage===s},on:{click:function(t){return e.switchLanguage(s)}}},[e._v(" "+e._s(a)+"\n ")])})),0)]),e._v(" "),e._l(e.actualLanguages,(function(a,s){return t("div",{directives:[{name:"show",rawName:"v-show",value:s===e.selectedLanguage,expression:"shorthand === selectedLanguage"}],key:s,staticClass:"tab-content"},[e._t(s)],2)}))],2)}),[],!1,null,null,null);t.default=u.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{384:function(e,t,a){"use strict";a.r(t);a(109);var s={props:{name:{type:String,default:"default"},isolated:{type:Boolean,default:!1},languages:{type:Object,required:!1}},data(){return{selectedLanguage:this.languages?Object.keys(this.languages)[0]:null,actualLanguages:this.languages}},computed:{root(){let e,t=this;for(;e=t.$parent;)t=e;return t},localStorageKey(){return"vuepress-plugin-code-switcher@"+this.name}},methods:{switchLanguage(e){if(this.isolated)return this.selectedLanguage=e;"undefined"!=typeof localStorage&&localStorage.setItem(this.localStorageKey,e),this.root.$emit("change",{name:this.name,value:e})},setConfiguredDefaultLanguages(){if(this.languages)return;const e=this.$page.codeSwitcherOptions;e&&e.groups&&e.groups[this.name]&&(this.actualLanguages=e.groups[this.name],this.selectedLanguage=Object.keys(this.actualLanguages)[0])}},created(){if(!this.isolated){if(this.setConfiguredDefaultLanguages(),!this.actualLanguages)throw new Error('You must specify either the "languages" prop or use the "groups" option when configuring the plugin.');if("undefined"!=typeof localStorage){let e=localStorage.getItem(this.localStorageKey);e&&-1!==Object.keys(this.actualLanguages).indexOf(e)&&(this.selectedLanguage=e)}this.root.$on("change",({name:e,value:t})=>{e===this.name&&(this.selectedLanguage=t)})}}},n=a(7),u=Object(n.a)(s,(function(){var e=this,t=e._self._c;return t("div",{staticClass:"code-switcher"},[t("div",{staticClass:"tab-header"},[t("ul",e._l(e.actualLanguages,(function(a,s){return t("li",{key:s,class:{active:e.selectedLanguage===s},on:{click:function(t){return e.switchLanguage(s)}}},[e._v(" "+e._s(a)+"\n ")])})),0)]),e._v(" "),e._l(e.actualLanguages,(function(a,s){return t("div",{directives:[{name:"show",rawName:"v-show",value:s===e.selectedLanguage,expression:"shorthand === selectedLanguage"}],key:s,staticClass:"tab-content"},[e._t(s)],2)}))],2)}),[],!1,null,null,null);t.default=u.exports}}]); \ No newline at end of file diff --git a/assets/js/28.c8b4b157.js b/assets/js/29.27884995.js similarity index 98% rename from assets/js/28.c8b4b157.js rename to assets/js/29.27884995.js index 39467b257..0580d0b56 100644 --- a/assets/js/28.c8b4b157.js +++ b/assets/js/29.27884995.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{381:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[t("code",[e._v("v0.0.116")]),e._v(" of LDK with added support for opening channels with "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/anchor-outputs",target:"_blank",rel:"noopener noreferrer"}},[e._v("anchor\noutputs"),t("OutboundLink")],1),e._v(" is live. This much-requested feature\nbrings multiple security and usability improvements to Lightning channels.")]),e._v(" "),t("p",[e._v("Lightning channels rely on pre-signed transactions that participants broadcast to the network if\nthey wish to close a channel unilaterally, e.g., when their counterparty is offline. Before\nintroducing anchor outputs to the Lightning protocol, participants continually negotiated their\ncommitment transaction’s fees based on the current block-space demand. This fee negotiation\nunfortunately came with its own set of problems. If participants disagreed on the proposed fee\nrange, a unilateral close made the channel unusable. Underestimating the required fee could result\nin loss of funds if an HTLC needed to be resolved on-chain, and overestimating would misallocate the\nchannel balance towards fees, potentially rendering the channel useless.")]),e._v(" "),t("p",[e._v("With anchor outputs, participants can now contribute the majority of fees required at the time of\nbroadcast by bumping the commitment transaction's fee via a child transaction using the\n"),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/cpfp",target:"_blank",rel:"noopener noreferrer"}},[e._v("Child-Pays-For-Parent (CPFP)"),t("OutboundLink")],1),e._v(" fee-bumping mechanism. A small\nportion of fees must still be allocated to commitment transactions to ensure they can enter nodes'\nmempools independently. This will be required until "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/package-relay",target:"_blank",rel:"noopener noreferrer"}},[e._v("package\nrelay"),t("OutboundLink")],1),e._v(" is deployed network-wide. At that point, we\ncan have a fixed 1 sat/vB commitment transaction that is likely to do away with the fee negotiation\nonce and for all, eliminating the most common cause of unilateral closes that we see today.")]),e._v(" "),t("p",[e._v("Given LDK's modularized design, support for anchor outputs posed a few challenges. As a\nLightning-only library, we do not include an on-chain wallet as a traditional node implementation\nwould, requiring manual integration work by the application developer. However, we were able to\nleverage our existing "),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/events/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("event-based\nAPI"),t("OutboundLink")],1),e._v(" to communicate that a commitment\nor HTLC transaction's fee needs to be bumped. The handling of these events is often non-trivial, so\nwe added a utility\n("),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/events/bump_transaction/struct.BumpTransactionEventHandler.html",target:"_blank",rel:"noopener noreferrer"}},[t("code",[e._v("BumpTransactionEventHandler")]),t("OutboundLink")],1),e._v(")\nto simplify required integration work. With this utility, an application developer only needs to\nprovide a view into their on-chain wallet for LDK to access confirmed UTXOs and sign them.")]),e._v(" "),t("p",[e._v("Note that node operators need to maintain a reserve of confirmed funds if they wish to exit a\nchannel unilaterally. LDK will not ensure this reserve is enforced, but we’re exploring "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/issues/2320",target:"_blank",rel:"noopener noreferrer"}},[e._v("possible\nways to do so"),t("OutboundLink")],1),e._v(". Without such\nenforcement, a node may open or accept more channels than its provisioned reserve allows it to\nhandle, potentially resulting in a loss of funds if any HTLCs need to be resolved on-chain. In the\nmeantime, application developers must determine whether their use case warrants such enforcement,\nthen implement it themselves. For example, a mobile user connected to a LSP could always defer to\nthe LSP to broadcast the latest state so that the user wouldn’t need to maintain a reserve.")]),e._v(" "),t("p",[e._v("While the feature is now available, we still consider it experimental. We're always seeking feedback\non how to improve our API and provide a better developer experience.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{385:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[t("code",[e._v("v0.0.116")]),e._v(" of LDK with added support for opening channels with "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/anchor-outputs",target:"_blank",rel:"noopener noreferrer"}},[e._v("anchor\noutputs"),t("OutboundLink")],1),e._v(" is live. This much-requested feature\nbrings multiple security and usability improvements to Lightning channels.")]),e._v(" "),t("p",[e._v("Lightning channels rely on pre-signed transactions that participants broadcast to the network if\nthey wish to close a channel unilaterally, e.g., when their counterparty is offline. Before\nintroducing anchor outputs to the Lightning protocol, participants continually negotiated their\ncommitment transaction’s fees based on the current block-space demand. This fee negotiation\nunfortunately came with its own set of problems. If participants disagreed on the proposed fee\nrange, a unilateral close made the channel unusable. Underestimating the required fee could result\nin loss of funds if an HTLC needed to be resolved on-chain, and overestimating would misallocate the\nchannel balance towards fees, potentially rendering the channel useless.")]),e._v(" "),t("p",[e._v("With anchor outputs, participants can now contribute the majority of fees required at the time of\nbroadcast by bumping the commitment transaction's fee via a child transaction using the\n"),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/cpfp",target:"_blank",rel:"noopener noreferrer"}},[e._v("Child-Pays-For-Parent (CPFP)"),t("OutboundLink")],1),e._v(" fee-bumping mechanism. A small\nportion of fees must still be allocated to commitment transactions to ensure they can enter nodes'\nmempools independently. This will be required until "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/package-relay",target:"_blank",rel:"noopener noreferrer"}},[e._v("package\nrelay"),t("OutboundLink")],1),e._v(" is deployed network-wide. At that point, we\ncan have a fixed 1 sat/vB commitment transaction that is likely to do away with the fee negotiation\nonce and for all, eliminating the most common cause of unilateral closes that we see today.")]),e._v(" "),t("p",[e._v("Given LDK's modularized design, support for anchor outputs posed a few challenges. As a\nLightning-only library, we do not include an on-chain wallet as a traditional node implementation\nwould, requiring manual integration work by the application developer. However, we were able to\nleverage our existing "),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/events/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("event-based\nAPI"),t("OutboundLink")],1),e._v(" to communicate that a commitment\nor HTLC transaction's fee needs to be bumped. The handling of these events is often non-trivial, so\nwe added a utility\n("),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/events/bump_transaction/struct.BumpTransactionEventHandler.html",target:"_blank",rel:"noopener noreferrer"}},[t("code",[e._v("BumpTransactionEventHandler")]),t("OutboundLink")],1),e._v(")\nto simplify required integration work. With this utility, an application developer only needs to\nprovide a view into their on-chain wallet for LDK to access confirmed UTXOs and sign them.")]),e._v(" "),t("p",[e._v("Note that node operators need to maintain a reserve of confirmed funds if they wish to exit a\nchannel unilaterally. LDK will not ensure this reserve is enforced, but we’re exploring "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/issues/2320",target:"_blank",rel:"noopener noreferrer"}},[e._v("possible\nways to do so"),t("OutboundLink")],1),e._v(". Without such\nenforcement, a node may open or accept more channels than its provisioned reserve allows it to\nhandle, potentially resulting in a loss of funds if any HTLCs need to be resolved on-chain. In the\nmeantime, application developers must determine whether their use case warrants such enforcement,\nthen implement it themselves. For example, a mobile user connected to a LSP could always defer to\nthe LSP to broadcast the latest state so that the user wouldn’t need to maintain a reserve.")]),e._v(" "),t("p",[e._v("While the feature is now available, we still consider it experimental. We're always seeking feedback\non how to improve our API and provide a better developer experience.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/29.983adc38.js b/assets/js/30.59a84bd4.js similarity index 99% rename from assets/js/29.983adc38.js rename to assets/js/30.59a84bd4.js index d10930995..5962f5c68 100644 --- a/assets/js/29.983adc38.js +++ b/assets/js/30.59a84bd4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{383:function(t,n,e){"use strict";e.r(n);var s=e(7),a=Object(s.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("p",[n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK Node"),n("OutboundLink")],1),t._v(" is a ready-to-go Lightning node library built using "),n("a",{attrs:{href:"https://lightningdevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK"),n("OutboundLink")],1),t._v(" and "),n("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),n("OutboundLink")],1),t._v(". LDK Node provides a straightforward interface and an integrated on-chain wallet, enabling users to quickly and easily set up a self-custodial Lightning node. With LDK Node, developers can get a Lightning Node up and running within a day.")]),t._v(" "),n("h2",{attrs:{id:"a-lightweight-solution"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#a-lightweight-solution"}},[t._v("#")]),t._v(" A Lightweight Solution")]),t._v(" "),n("p",[t._v("LDK fully implements the Lightning protocol as a highly modular Rust library. LDK's flexibility allows developers to integrate Lightning functionality into "),n("a",{attrs:{href:"https://lightningdevkit.org/case-studies/",target:"_blank",rel:"noopener noreferrer"}},[t._v("many types of applications"),n("OutboundLink")],1),t._v(", including those with pre-existing infrastructure or complex architectures. The public API comprises more than 900 exposed methods, letting users adjust and interact with protocol layers in great detail. While this customization is great for builders, it often comes with the added cost of increased complexity.")]),t._v(" "),n("p",[t._v("LDK provides sane defaults where possible. However, correctly and effectively setting up all interconnected modules requires a deeper understanding of protocol fundamentals and some familiarity with the LDK API. Moreover, because LDK adheres to the separation-of-concerns principle, it is wallet-agnostic and deliberately doesn't come with an included on-chain wallet. Therefore, the integration with a suitable on-chain wallet is left to the user.")]),t._v(" "),n("p",[t._v("As a result, it can take a bit of effort to get started with LDK. That's why we created LDK Node, a more fully-baked solution.")]),t._v(" "),n("h2",{attrs:{id:"ldk-node-simplifying-self-custodial-lightning-integration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-simplifying-self-custodial-lightning-integration"}},[t._v("#")]),t._v(" LDK Node: Simplifying Self-custodial Lightning Integration")]),t._v(" "),n("p",[t._v("LDK Node was designed to hide protocol complexities without infringing on usability. LDK Node's much smaller API surface makes its reduced complexity evident. Compared to LDK's above 900 exposed methods, LDK Node's API currently only encompasses around 30 API calls. While simplicity and minimalism are at its core, LDK Node remains configurable enough to operate a fully functional self-custodial Lightning node in various use cases.")]),t._v(" "),n("p",[t._v("There is a trade-off between simplicity and expressiveness when designing an API while handling protocol complexity. The API needs to become more complicated to increase configurability and the interconnectivity of components. As a result, the user must spend more time examining, learning, and scrutinizing the API before finally being able to use it. While the LDK API errs on the side of expressiveness, LDK Node leans towards simplicity.")]),t._v(" "),n("p",[t._v("This first release of LDK Node comes with an opinionated set of design choices and ready-to-go modules:")]),t._v(" "),n("ul",[n("li",[t._v("The integrated "),n("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),n("OutboundLink")],1),t._v(" wallet handles on-chain data.")]),t._v(" "),n("li",[t._v("Chain data is sourced from an "),n("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[t._v("Esplora"),n("OutboundLink")],1),t._v(" server, while support for Electrum and "),n("code",[t._v("bitcoind")]),t._v(" RPC will follow soon.")]),t._v(" "),n("li",[t._v("Wallet and channel state may be persisted to an "),n("a",{attrs:{href:"https://sqlite.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQLite"),n("OutboundLink")],1),t._v(" database, to file system, or to a custom back-end to be implemented by the user. Support for "),n("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[t._v("Versioned Storage Service (VSS)"),n("OutboundLink")],1),t._v(" will follow soon.")]),t._v(" "),n("li",[t._v("Gossip data may be sourced via Lightning's peer-to-peer network or the "),n("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/0.0.115/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rapid Gossip Sync (RGS)"),n("OutboundLink")],1),t._v(" protocol.")]),t._v(" "),n("li",[t._v("Entropy for Lightning and on-chain wallets may be sourced from raw bytes or a "),n("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[t._v("BIP39"),n("OutboundLink")],1),t._v(" mnemonic. In addition, LDK Node offers the means to generate and persist the entropy bytes to disk.")])]),t._v(" "),n("h2",{attrs:{id:"mobile-first-self-custody"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#mobile-first-self-custody"}},[t._v("#")]),t._v(" Mobile-first Self-Custody")]),t._v(" "),n("p",[t._v("The main goal of the Lightning protocol is to enable fast, private, and secure Bitcoin transactions for the end-user. However, today most Lightning deployments are custodial services that may only be queried by the client device in the end-user's hands. This is understandable: deploying self-custodial Lightning nodes on end-user devices can take a lot of work to get right, as there are many pitfalls to avoid.")]),t._v(" "),n("p",[t._v("To this end, one of the primary goals of LDK Node is to simplify the integration of self-custodial Lightning nodes in mobile applications. The features of the initial release are centered around mobile deployments. The integration with an Esplora chain data source and a Rapid Gossip Sync server allows the node to operate in mobile environments that may be limited in terms of bandwidth and overall traffic quota.")]),t._v(" "),n("p",[t._v("LDK Node itself is written in "),n("a",{attrs:{href:"https://www.rust-lang.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust"),n("OutboundLink")],1),t._v(" and may therefore be natively added as a library dependency to any "),n("code",[t._v("std")]),t._v(" Rust program. However, beyond its Rust API, it offers "),n("a",{attrs:{href:"https://www.swift.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Swift"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://kotlinlang.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Kotlin"),n("OutboundLink")],1),t._v(", and "),n("a",{attrs:{href:"https://www.python.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Python"),n("OutboundLink")],1),t._v(" language bindings based on "),n("a",{attrs:{href:"https://github.com/mozilla/uniffi-rs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("UniFFI"),n("OutboundLink")],1),t._v(". Moreover, "),n("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("Flutter"),n("OutboundLink")],1),t._v(" bindings are also available to allow usage of the LDK Node library in mobile environments.")]),t._v(" "),n("h2",{attrs:{id:"getting-started"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),n("p",[t._v("The primary abstraction of the library is the "),n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/struct.Node.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Node")]),n("OutboundLink")],1),t._v(", which can be retrieved by setting up and configuring a "),n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/struct.Builder.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Builder")]),n("OutboundLink")],1),t._v(" to your liking and calling one of the "),n("code",[t._v("build")]),t._v(" methods. "),n("code",[t._v("Node")]),t._v(" can then be controlled via commands such as "),n("code",[t._v("start")]),t._v(", "),n("code",[t._v("stop")]),t._v(", "),n("code",[t._v("connect_open_channel")]),t._v(", "),n("code",[t._v("send_payment")]),t._v(", etc.")]),t._v(" "),n("p",[n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Read Full API Documentation"),n("OutboundLink")],1)]),t._v(" "),n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetAddress")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning_invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_esplora_server")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://blockstream.info/testnet/api"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_gossip_source_rgs")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://rapidsync.lightningdevkit.org/testnet/snapshot"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" builder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" funding_address "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_onchain_address")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .. fund address ..")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node_id "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NODE_ID"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node_addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetAddress")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"IP_ADDR:PORT"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect_open_channel")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("node_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" node_addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("wait_next_event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EVENT: {:?}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("event_handled")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"INVOICE_STR"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stop")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"outlook"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#outlook"}},[t._v("#")]),t._v(" Outlook")]),t._v(" "),n("p",[t._v("The 0.1 release is only the beginning for LDK Node. Development for the next release has already started, and we'll be looking to add support for sourcing chain data from Electrum or "),n("code",[t._v("bitcoind")]),t._v(" RPC, and supporting persistence to a "),n("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[t._v("VSS"),n("OutboundLink")],1),t._v(" backend (see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node/issues/107",target:"_blank",rel:"noopener noreferrer"}},[t._v("v0.2 tracking issue"),n("OutboundLink")],1),t._v("). Additionally, integration with the "),n("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSP specification"),n("OutboundLink")],1),t._v(" is actively being worked on (see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-lsp-client",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSP Client"),n("OutboundLink")],1),t._v(" repository) and will come to LDK Node as soon as it's ready. Beyond these planned feature updates to the LDK Node library, we're also considering further deployment targets, including adding server-grade modules in the future.")]),t._v(" "),n("h2",{attrs:{id:"further-resources"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#further-resources"}},[t._v("#")]),t._v(" Further Resources")]),t._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github Repository"),n("OutboundLink")],1)]),t._v(" "),n("li",[n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/",target:"_blank",rel:"noopener noreferrer"}},[t._v("API Documentation"),n("OutboundLink")],1)]),t._v(" "),n("li",[n("a",{attrs:{href:"https://crates.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Crate"),n("OutboundLink")],1)])]),t._v(" "),n("h2",{attrs:{id:"showcases"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#showcases"}},[t._v("#")]),t._v(" Showcases")]),t._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://github.com/reez/Monday",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monday Wallet: Example wallet built with on LDK Node Swift bindings"),n("OutboundLink")],1)])])])}),[],!1,null,null,null);n.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{386:function(t,n,e){"use strict";e.r(n);var s=e(7),a=Object(s.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("p",[n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK Node"),n("OutboundLink")],1),t._v(" is a ready-to-go Lightning node library built using "),n("a",{attrs:{href:"https://lightningdevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK"),n("OutboundLink")],1),t._v(" and "),n("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),n("OutboundLink")],1),t._v(". LDK Node provides a straightforward interface and an integrated on-chain wallet, enabling users to quickly and easily set up a self-custodial Lightning node. With LDK Node, developers can get a Lightning Node up and running within a day.")]),t._v(" "),n("h2",{attrs:{id:"a-lightweight-solution"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#a-lightweight-solution"}},[t._v("#")]),t._v(" A Lightweight Solution")]),t._v(" "),n("p",[t._v("LDK fully implements the Lightning protocol as a highly modular Rust library. LDK's flexibility allows developers to integrate Lightning functionality into "),n("a",{attrs:{href:"https://lightningdevkit.org/case-studies/",target:"_blank",rel:"noopener noreferrer"}},[t._v("many types of applications"),n("OutboundLink")],1),t._v(", including those with pre-existing infrastructure or complex architectures. The public API comprises more than 900 exposed methods, letting users adjust and interact with protocol layers in great detail. While this customization is great for builders, it often comes with the added cost of increased complexity.")]),t._v(" "),n("p",[t._v("LDK provides sane defaults where possible. However, correctly and effectively setting up all interconnected modules requires a deeper understanding of protocol fundamentals and some familiarity with the LDK API. Moreover, because LDK adheres to the separation-of-concerns principle, it is wallet-agnostic and deliberately doesn't come with an included on-chain wallet. Therefore, the integration with a suitable on-chain wallet is left to the user.")]),t._v(" "),n("p",[t._v("As a result, it can take a bit of effort to get started with LDK. That's why we created LDK Node, a more fully-baked solution.")]),t._v(" "),n("h2",{attrs:{id:"ldk-node-simplifying-self-custodial-lightning-integration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-simplifying-self-custodial-lightning-integration"}},[t._v("#")]),t._v(" LDK Node: Simplifying Self-custodial Lightning Integration")]),t._v(" "),n("p",[t._v("LDK Node was designed to hide protocol complexities without infringing on usability. LDK Node's much smaller API surface makes its reduced complexity evident. Compared to LDK's above 900 exposed methods, LDK Node's API currently only encompasses around 30 API calls. While simplicity and minimalism are at its core, LDK Node remains configurable enough to operate a fully functional self-custodial Lightning node in various use cases.")]),t._v(" "),n("p",[t._v("There is a trade-off between simplicity and expressiveness when designing an API while handling protocol complexity. The API needs to become more complicated to increase configurability and the interconnectivity of components. As a result, the user must spend more time examining, learning, and scrutinizing the API before finally being able to use it. While the LDK API errs on the side of expressiveness, LDK Node leans towards simplicity.")]),t._v(" "),n("p",[t._v("This first release of LDK Node comes with an opinionated set of design choices and ready-to-go modules:")]),t._v(" "),n("ul",[n("li",[t._v("The integrated "),n("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),n("OutboundLink")],1),t._v(" wallet handles on-chain data.")]),t._v(" "),n("li",[t._v("Chain data is sourced from an "),n("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[t._v("Esplora"),n("OutboundLink")],1),t._v(" server, while support for Electrum and "),n("code",[t._v("bitcoind")]),t._v(" RPC will follow soon.")]),t._v(" "),n("li",[t._v("Wallet and channel state may be persisted to an "),n("a",{attrs:{href:"https://sqlite.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("SQLite"),n("OutboundLink")],1),t._v(" database, to file system, or to a custom back-end to be implemented by the user. Support for "),n("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[t._v("Versioned Storage Service (VSS)"),n("OutboundLink")],1),t._v(" will follow soon.")]),t._v(" "),n("li",[t._v("Gossip data may be sourced via Lightning's peer-to-peer network or the "),n("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/0.0.115/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rapid Gossip Sync (RGS)"),n("OutboundLink")],1),t._v(" protocol.")]),t._v(" "),n("li",[t._v("Entropy for Lightning and on-chain wallets may be sourced from raw bytes or a "),n("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[t._v("BIP39"),n("OutboundLink")],1),t._v(" mnemonic. In addition, LDK Node offers the means to generate and persist the entropy bytes to disk.")])]),t._v(" "),n("h2",{attrs:{id:"mobile-first-self-custody"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#mobile-first-self-custody"}},[t._v("#")]),t._v(" Mobile-first Self-Custody")]),t._v(" "),n("p",[t._v("The main goal of the Lightning protocol is to enable fast, private, and secure Bitcoin transactions for the end-user. However, today most Lightning deployments are custodial services that may only be queried by the client device in the end-user's hands. This is understandable: deploying self-custodial Lightning nodes on end-user devices can take a lot of work to get right, as there are many pitfalls to avoid.")]),t._v(" "),n("p",[t._v("To this end, one of the primary goals of LDK Node is to simplify the integration of self-custodial Lightning nodes in mobile applications. The features of the initial release are centered around mobile deployments. The integration with an Esplora chain data source and a Rapid Gossip Sync server allows the node to operate in mobile environments that may be limited in terms of bandwidth and overall traffic quota.")]),t._v(" "),n("p",[t._v("LDK Node itself is written in "),n("a",{attrs:{href:"https://www.rust-lang.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust"),n("OutboundLink")],1),t._v(" and may therefore be natively added as a library dependency to any "),n("code",[t._v("std")]),t._v(" Rust program. However, beyond its Rust API, it offers "),n("a",{attrs:{href:"https://www.swift.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Swift"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://kotlinlang.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Kotlin"),n("OutboundLink")],1),t._v(", and "),n("a",{attrs:{href:"https://www.python.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Python"),n("OutboundLink")],1),t._v(" language bindings based on "),n("a",{attrs:{href:"https://github.com/mozilla/uniffi-rs/",target:"_blank",rel:"noopener noreferrer"}},[t._v("UniFFI"),n("OutboundLink")],1),t._v(". Moreover, "),n("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("Flutter"),n("OutboundLink")],1),t._v(" bindings are also available to allow usage of the LDK Node library in mobile environments.")]),t._v(" "),n("h2",{attrs:{id:"getting-started"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),n("p",[t._v("The primary abstraction of the library is the "),n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/struct.Node.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Node")]),n("OutboundLink")],1),t._v(", which can be retrieved by setting up and configuring a "),n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/struct.Builder.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Builder")]),n("OutboundLink")],1),t._v(" to your liking and calling one of the "),n("code",[t._v("build")]),t._v(" methods. "),n("code",[t._v("Node")]),t._v(" can then be controlled via commands such as "),n("code",[t._v("start")]),t._v(", "),n("code",[t._v("stop")]),t._v(", "),n("code",[t._v("connect_open_channel")]),t._v(", "),n("code",[t._v("send_payment")]),t._v(", etc.")]),t._v(" "),n("p",[n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Read Full API Documentation"),n("OutboundLink")],1)]),t._v(" "),n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetAddress")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning_invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_esplora_server")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://blockstream.info/testnet/api"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tbuilder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_gossip_source_rgs")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://rapidsync.lightningdevkit.org/testnet/snapshot"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" builder"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" funding_address "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_onchain_address")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// .. fund address ..")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node_id "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NODE_ID"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node_addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetAddress")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"IP_ADDR:PORT"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect_open_channel")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("node_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" node_addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("wait_next_event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EVENT: {:?}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("event_handled")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"INVOICE_STR"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\tnode"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stop")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"outlook"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#outlook"}},[t._v("#")]),t._v(" Outlook")]),t._v(" "),n("p",[t._v("The 0.1 release is only the beginning for LDK Node. Development for the next release has already started, and we'll be looking to add support for sourcing chain data from Electrum or "),n("code",[t._v("bitcoind")]),t._v(" RPC, and supporting persistence to a "),n("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[t._v("VSS"),n("OutboundLink")],1),t._v(" backend (see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node/issues/107",target:"_blank",rel:"noopener noreferrer"}},[t._v("v0.2 tracking issue"),n("OutboundLink")],1),t._v("). Additionally, integration with the "),n("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSP specification"),n("OutboundLink")],1),t._v(" is actively being worked on (see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-lsp-client",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSP Client"),n("OutboundLink")],1),t._v(" repository) and will come to LDK Node as soon as it's ready. Beyond these planned feature updates to the LDK Node library, we're also considering further deployment targets, including adding server-grade modules in the future.")]),t._v(" "),n("h2",{attrs:{id:"further-resources"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#further-resources"}},[t._v("#")]),t._v(" Further Resources")]),t._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("Github Repository"),n("OutboundLink")],1)]),t._v(" "),n("li",[n("a",{attrs:{href:"https://docs.rs/ldk-node/*/ldk_node/",target:"_blank",rel:"noopener noreferrer"}},[t._v("API Documentation"),n("OutboundLink")],1)]),t._v(" "),n("li",[n("a",{attrs:{href:"https://crates.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Crate"),n("OutboundLink")],1)])]),t._v(" "),n("h2",{attrs:{id:"showcases"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#showcases"}},[t._v("#")]),t._v(" Showcases")]),t._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://github.com/reez/Monday",target:"_blank",rel:"noopener noreferrer"}},[t._v("Monday Wallet: Example wallet built with on LDK Node Swift bindings"),n("OutboundLink")],1)])])])}),[],!1,null,null,null);n.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/30.ac89cbd4.js b/assets/js/31.975f9e88.js similarity index 99% rename from assets/js/30.ac89cbd4.js rename to assets/js/31.975f9e88.js index 335f0ff0e..b96d09a36 100644 --- a/assets/js/30.ac89cbd4.js +++ b/assets/js/31.975f9e88.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{382:function(e,t,a){"use strict";a.r(t);var n=a(7),s=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("If you've run a Lightning node, you'll have noticed that initialization can be time-consuming. Merely opening a channel requires six block confirmations or about one hour. However, even if your node already has open channels but has been offline for a while, restarting it still requires fetching the latest channel graph data (commonly referred to as \"gossip”) and verifying that all its channels have remained intact.")]),e._v(" "),t("p",[e._v("While most Lightning implementations have mechanisms to quickly catch up to the latest block, one bottleneck that may remain is the exchange of aforementioned gossip, which rarely takes more than a couple of minutes but significantly impacts UX when initiating locally-routed payments from a mobile device. Assuming that an app remains closed until you need to send a payment, even a one-minute waiting period becomes a major payment flow disruptor. This issue is commonly resolved by sharing the intended payment recipient with a Lightning Service Provider, thus compromising privacy to offload the route calculation to a server.")]),e._v(" "),t("p",[e._v("For that reason, we're very excited to announce Rapid Gossip Sync, a protocol that allows nodes to catch up with channel gossip data by relying on semi-trusted servers.")]),e._v(" "),t("h2",{attrs:{id:"exchanging-gossip-today"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#exchanging-gossip-today"}},[e._v("#")]),e._v(" Exchanging Gossip Today")]),e._v(" "),t("p",[e._v("Before we delve too deeply into the optimizations that Rapid Gossip Sync relies on, first a primer on how gossip works today. It involves three main message types: channel announcements, channel updates, and node announcements. (The last of which isn’t really relevant to this post.)")]),e._v(" "),t("p",[e._v("As their names imply, channel announcements are sent when a public channel opens, and updates when changes are made to a channel. One peculiar characteristic of channels is that they aren't symmetrical: depending on the direction, some of their properties may vary. For instance, if Alice and Bob have a channel, Alice may charge higher fees for forwarding payments to Bob than Bob to Alice. Unlike channel updates, channel announcements do not carry directional information, so that scenario would require that different channel updates be broadcast to the network for each direction. Similarly, opening a new channel also requires sending at least two channel updates to initialize direction-specific properties.")]),e._v(" "),t("p",[e._v("One of the noteworthy properties of gossip is that a lot of data is duplicated across messages. For example, each channel announcement and update contains the genesis block hash. Similarly, each channel announcement contains both nodes’ public keys, exacerbating data redundancy for well-connected nodes. So, to reduce bandwidth requirements, we decided to see if we could strip data to create a more efficient way of conveying the same information.")]),e._v(" "),t("p",[e._v("In the next few paragraphs, we'll outline a selection of the various optimizations we came up with.")]),e._v(" "),t("h2",{attrs:{id:"rapid-gossip-sync"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rapid-gossip-sync"}},[e._v("#")]),e._v(" Rapid Gossip Sync")]),e._v(" "),t("p",[e._v("Firstly, the idea of Rapid Gossip Sync is that gossip data is pre-processed by one or multiple semi-trusted servers. These validate the signatures sent via regular gossip and verify the channels against the blockchain. This should obviate client-side signature verification and allow us to entirely remove signatures from the messages.")]),e._v(" "),t("p",[e._v("Secondly, the server sends batches of gossip data, representing snapshots of recent channel graphs. Given that the server batches the data, global properties across all announcements and updates (such as the chain hash) can be stripped out and sent just once. Similarly, since clients are primarily interested in new information, a single timestamp (the latest one) suffices to determine what data the client has or hasn't seen before when it requests the latest gossip snapshot.")]),e._v(" "),t("p",[e._v("The most crucial optimization that comes with Rapid Gossip Sync is that it doesn't send redundant updates. So even if a node sends 100 channel updates, and the only mutated property is its base fee, there would be no need to send out any other unchanged properties. To do that, we overloaded the channel flag byte, which would otherwise only use two bits to indicate an update's affected direction and whether a channel is disabled.")]),e._v(" "),t("p",[e._v("Channel updates are sent frequently and often refer to channels the client hasn't seen before, meaning that the server must include all properties, not just the mutated ones. This realization led us to notice that many properties were set to the same value across different channel updates, so we decided to measure what values occurred most frequently. Then, to reduce data overhead, we declare those most commonly occurring values as defaults at the start of every gossip snapshot. Any property whose value matches the default can be omitted from the snapshot if a channel update refers to a previously unknown channel. The only difficulty arising from that optimization is distinguishing whether a channel update is new or incremental. As it happens, the last remaining bit of the channel flags lends itself perfectly for this purpose. This way, when an update is new, a set property bit will indicate a deviation from the default specified at the beginning of the snapshot. Otherwise, that same bit, when set, would instead indicate a mutation. In either case, when a property's bit flag is not set, its corresponding value needn't be sent over the wire.")]),e._v(" "),t("p",[e._v("Finally, short channel IDs need to be specified for each announcement and update. Since they require 8 bytes per message, we were able to reduce memory requirements by sorting announcements and updates incrementally, and then successively specifying channel IDs in terms of their relative delta, which can be expressed in fewer than 8 bytes by using the BigSize data type.")]),e._v(" "),t("h2",{attrs:{id:"rapid-gossip-sync-server"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rapid-gossip-sync-server"}},[e._v("#")]),e._v(" Rapid Gossip Sync Server")]),e._v(" "),t("p",[e._v("The Rapid Gossip Sync protocol can only function with a corresponding server. Its operating principle is straightforward: connect to a set of peers on the Lightning Network, monitor the gossip, and persist the timestamped changes to a database. Upon receiving a client’s request, determine which changes have occurred after the provided timestamp and serialize the delta in Rapid Gossip Sync’s compact snapshot format. However, this comes with some caveats.")]),e._v(" "),t("p",[e._v('Channel updates sometimes percolate slowly through the network, resulting in disagreements between the included timestamp and what the server detects. To avoid ambiguity, the server marks all announcements and updates with a "seen" timestamp, canonically ordering all events and making difference determination straightforward. Each snapshot returned to the client includes the latest "seen" timestamp across every announcement and update.')]),e._v(" "),t("p",[e._v("Additionally, calculating graph delta on the fly is resource-intensive and can last tens of seconds. To avoid this, the Rapid Gossip Sync server calculates static delta snapshots at regular 24-hour-intervals. This means that any snapshot a client receives is, on average, 12 hours behind the current state of the graph. Depending on your use case, snapshot calculation frequency may be tweaked.")]),e._v(" "),t("h2",{attrs:{id:"trust-model"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#trust-model"}},[e._v("#")]),e._v(" Trust Model")]),e._v(" "),t("p",[e._v("Many mobile Lightning wallets delegate routing to servers, which jeopardizes some of the Lightning Network’s privacy benefits. Despite the marginal improvements stemming from the fact that transactions don’t end up on-chain, your payment history remains one data dump away from becoming public knowledge.")]),e._v(" "),t("p",[e._v("By relying on a Rapid Gossip Sync server, mobile wallets no longer need to compromise UX to gain the privacy benefit of client-side routing. The trust model shifts the onus of verifying the channel graph against the blockchain and validating node signatures to the server. That would allow a malicious Rapid Gossip Sync server to partially omit graph data to force payments to be routed through itself. If the server is widely used, it could also concentrate routing through another network node to facilitate a denial of service attack.")]),e._v(" "),t("p",[e._v("Considering that most mobile Lightning wallets communicate with their developers' servers, these concerns can be easily mitigated by deploying a Rapid Gossip Sync server to enable your mobile wallet to route privately without third parties or sacrificing UX.")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("Let's look at our data usage improvements with the above optimizations factored in.")]),e._v(" "),t("p",[e._v("Without Rapid Gossip Sync, we measured sync data using a random set of 80,000 channel announcements and 160,000 channel updates and identified an average of approximately 53MB.")]),e._v(" "),t("p",[e._v("With Rapid Gossip Sync, a snapshot representing the same graph took up 4.7MB and, after gzip, only 2MB. The time to process and apply that snapshot on a mobile phone was less than 0.4 seconds. For more detailed numbers, please refer to the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/tree/main/lightning-rapid-gossip-sync",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync README"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We're excited for you to try Rapid Gossip Sync out and invite you to look at the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rapid-gossip-sync-server",target:"_blank",rel:"noopener noreferrer"}},[e._v("server code"),t("OutboundLink")],1),e._v(". If you don't wish to operate a Rapid Gossip Sync snapshotting server, feel free to try our deployment, which is available at "),t("a",{attrs:{href:"https://rapidsync.lightningdevkit.org",target:"_blank",rel:"noopener noreferrer"}},[e._v("rapidsync.lightningdevkit.org"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{390:function(e,t,a){"use strict";a.r(t);var n=a(7),s=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("If you've run a Lightning node, you'll have noticed that initialization can be time-consuming. Merely opening a channel requires six block confirmations or about one hour. However, even if your node already has open channels but has been offline for a while, restarting it still requires fetching the latest channel graph data (commonly referred to as \"gossip”) and verifying that all its channels have remained intact.")]),e._v(" "),t("p",[e._v("While most Lightning implementations have mechanisms to quickly catch up to the latest block, one bottleneck that may remain is the exchange of aforementioned gossip, which rarely takes more than a couple of minutes but significantly impacts UX when initiating locally-routed payments from a mobile device. Assuming that an app remains closed until you need to send a payment, even a one-minute waiting period becomes a major payment flow disruptor. This issue is commonly resolved by sharing the intended payment recipient with a Lightning Service Provider, thus compromising privacy to offload the route calculation to a server.")]),e._v(" "),t("p",[e._v("For that reason, we're very excited to announce Rapid Gossip Sync, a protocol that allows nodes to catch up with channel gossip data by relying on semi-trusted servers.")]),e._v(" "),t("h2",{attrs:{id:"exchanging-gossip-today"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#exchanging-gossip-today"}},[e._v("#")]),e._v(" Exchanging Gossip Today")]),e._v(" "),t("p",[e._v("Before we delve too deeply into the optimizations that Rapid Gossip Sync relies on, first a primer on how gossip works today. It involves three main message types: channel announcements, channel updates, and node announcements. (The last of which isn’t really relevant to this post.)")]),e._v(" "),t("p",[e._v("As their names imply, channel announcements are sent when a public channel opens, and updates when changes are made to a channel. One peculiar characteristic of channels is that they aren't symmetrical: depending on the direction, some of their properties may vary. For instance, if Alice and Bob have a channel, Alice may charge higher fees for forwarding payments to Bob than Bob to Alice. Unlike channel updates, channel announcements do not carry directional information, so that scenario would require that different channel updates be broadcast to the network for each direction. Similarly, opening a new channel also requires sending at least two channel updates to initialize direction-specific properties.")]),e._v(" "),t("p",[e._v("One of the noteworthy properties of gossip is that a lot of data is duplicated across messages. For example, each channel announcement and update contains the genesis block hash. Similarly, each channel announcement contains both nodes’ public keys, exacerbating data redundancy for well-connected nodes. So, to reduce bandwidth requirements, we decided to see if we could strip data to create a more efficient way of conveying the same information.")]),e._v(" "),t("p",[e._v("In the next few paragraphs, we'll outline a selection of the various optimizations we came up with.")]),e._v(" "),t("h2",{attrs:{id:"rapid-gossip-sync"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rapid-gossip-sync"}},[e._v("#")]),e._v(" Rapid Gossip Sync")]),e._v(" "),t("p",[e._v("Firstly, the idea of Rapid Gossip Sync is that gossip data is pre-processed by one or multiple semi-trusted servers. These validate the signatures sent via regular gossip and verify the channels against the blockchain. This should obviate client-side signature verification and allow us to entirely remove signatures from the messages.")]),e._v(" "),t("p",[e._v("Secondly, the server sends batches of gossip data, representing snapshots of recent channel graphs. Given that the server batches the data, global properties across all announcements and updates (such as the chain hash) can be stripped out and sent just once. Similarly, since clients are primarily interested in new information, a single timestamp (the latest one) suffices to determine what data the client has or hasn't seen before when it requests the latest gossip snapshot.")]),e._v(" "),t("p",[e._v("The most crucial optimization that comes with Rapid Gossip Sync is that it doesn't send redundant updates. So even if a node sends 100 channel updates, and the only mutated property is its base fee, there would be no need to send out any other unchanged properties. To do that, we overloaded the channel flag byte, which would otherwise only use two bits to indicate an update's affected direction and whether a channel is disabled.")]),e._v(" "),t("p",[e._v("Channel updates are sent frequently and often refer to channels the client hasn't seen before, meaning that the server must include all properties, not just the mutated ones. This realization led us to notice that many properties were set to the same value across different channel updates, so we decided to measure what values occurred most frequently. Then, to reduce data overhead, we declare those most commonly occurring values as defaults at the start of every gossip snapshot. Any property whose value matches the default can be omitted from the snapshot if a channel update refers to a previously unknown channel. The only difficulty arising from that optimization is distinguishing whether a channel update is new or incremental. As it happens, the last remaining bit of the channel flags lends itself perfectly for this purpose. This way, when an update is new, a set property bit will indicate a deviation from the default specified at the beginning of the snapshot. Otherwise, that same bit, when set, would instead indicate a mutation. In either case, when a property's bit flag is not set, its corresponding value needn't be sent over the wire.")]),e._v(" "),t("p",[e._v("Finally, short channel IDs need to be specified for each announcement and update. Since they require 8 bytes per message, we were able to reduce memory requirements by sorting announcements and updates incrementally, and then successively specifying channel IDs in terms of their relative delta, which can be expressed in fewer than 8 bytes by using the BigSize data type.")]),e._v(" "),t("h2",{attrs:{id:"rapid-gossip-sync-server"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rapid-gossip-sync-server"}},[e._v("#")]),e._v(" Rapid Gossip Sync Server")]),e._v(" "),t("p",[e._v("The Rapid Gossip Sync protocol can only function with a corresponding server. Its operating principle is straightforward: connect to a set of peers on the Lightning Network, monitor the gossip, and persist the timestamped changes to a database. Upon receiving a client’s request, determine which changes have occurred after the provided timestamp and serialize the delta in Rapid Gossip Sync’s compact snapshot format. However, this comes with some caveats.")]),e._v(" "),t("p",[e._v('Channel updates sometimes percolate slowly through the network, resulting in disagreements between the included timestamp and what the server detects. To avoid ambiguity, the server marks all announcements and updates with a "seen" timestamp, canonically ordering all events and making difference determination straightforward. Each snapshot returned to the client includes the latest "seen" timestamp across every announcement and update.')]),e._v(" "),t("p",[e._v("Additionally, calculating graph delta on the fly is resource-intensive and can last tens of seconds. To avoid this, the Rapid Gossip Sync server calculates static delta snapshots at regular 24-hour-intervals. This means that any snapshot a client receives is, on average, 12 hours behind the current state of the graph. Depending on your use case, snapshot calculation frequency may be tweaked.")]),e._v(" "),t("h2",{attrs:{id:"trust-model"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#trust-model"}},[e._v("#")]),e._v(" Trust Model")]),e._v(" "),t("p",[e._v("Many mobile Lightning wallets delegate routing to servers, which jeopardizes some of the Lightning Network’s privacy benefits. Despite the marginal improvements stemming from the fact that transactions don’t end up on-chain, your payment history remains one data dump away from becoming public knowledge.")]),e._v(" "),t("p",[e._v("By relying on a Rapid Gossip Sync server, mobile wallets no longer need to compromise UX to gain the privacy benefit of client-side routing. The trust model shifts the onus of verifying the channel graph against the blockchain and validating node signatures to the server. That would allow a malicious Rapid Gossip Sync server to partially omit graph data to force payments to be routed through itself. If the server is widely used, it could also concentrate routing through another network node to facilitate a denial of service attack.")]),e._v(" "),t("p",[e._v("Considering that most mobile Lightning wallets communicate with their developers' servers, these concerns can be easily mitigated by deploying a Rapid Gossip Sync server to enable your mobile wallet to route privately without third parties or sacrificing UX.")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("Let's look at our data usage improvements with the above optimizations factored in.")]),e._v(" "),t("p",[e._v("Without Rapid Gossip Sync, we measured sync data using a random set of 80,000 channel announcements and 160,000 channel updates and identified an average of approximately 53MB.")]),e._v(" "),t("p",[e._v("With Rapid Gossip Sync, a snapshot representing the same graph took up 4.7MB and, after gzip, only 2MB. The time to process and apply that snapshot on a mobile phone was less than 0.4 seconds. For more detailed numbers, please refer to the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/tree/main/lightning-rapid-gossip-sync",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync README"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We're excited for you to try Rapid Gossip Sync out and invite you to look at the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rapid-gossip-sync-server",target:"_blank",rel:"noopener noreferrer"}},[e._v("server code"),t("OutboundLink")],1),e._v(". If you don't wish to operate a Rapid Gossip Sync snapshotting server, feel free to try our deployment, which is available at "),t("a",{attrs:{href:"https://rapidsync.lightningdevkit.org",target:"_blank",rel:"noopener noreferrer"}},[e._v("rapidsync.lightningdevkit.org"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/31.6b7541e7.js b/assets/js/32.5c181b9a.js similarity index 99% rename from assets/js/31.6b7541e7.js rename to assets/js/32.5c181b9a.js index 513c67498..909a26392 100644 --- a/assets/js/31.6b7541e7.js +++ b/assets/js/32.5c181b9a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{387:function(e,t,n){"use strict";n.r(t);var i=n(7),r=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("We are excited to release our first blog post, we have a lot to share and a lot to build. We’ll be updating this blog regularly with what we’re working on, new features and the details on new releases.")]),e._v(" "),t("h2",{attrs:{id:"ldwho"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldwho"}},[e._v("#")]),e._v(" LDWho?")]),e._v(" "),t("p",[e._v("If you’re reading this, you probably know something about the Lightning Development Kit, the easy-to-use open-source tool that simplifies how developers add highly secure, privacy-preserving Lightning functionality to bitcoin applications. What you might not know is how it got started.")]),e._v(" "),t("p",[e._v("LDK began as a side project developed by Matt Corallo "),t("a",{attrs:{href:"https://twitter.com/TheBlueMatt",target:"_blank",rel:"noopener noreferrer"}},[e._v("@TheBlueMatt"),t("OutboundLink")],1),e._v(" in "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/commit/6185a2819090bd077954244c5e2adaab5efcaa1a",target:"_blank",rel:"noopener noreferrer"}},[e._v("2018"),t("OutboundLink")],1),e._v(" called rust-lightning. One of Matt’s earliest rust-lightning "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=bfAz0vYlDAI",target:"_blank",rel:"noopener noreferrer"}},[e._v("demos"),t("OutboundLink")],1),e._v(" shows how you can take a full Lightning implementation (managing channels, generating messages to send to peers, signatures, on-chain punishment, etc), and use it to create a library with high-level APIs, so developers can build more and agonize less.")]),e._v(" "),t("p",[e._v("This highly specialized library needed to be flexible enough to let developers customize areas like on-chain wallet creation, sourcing blockchain data, and backing up channel states while paving the way for them to make those critical decisions at 10x speed.")]),e._v(" "),t("p",[e._v("Initially supported by "),t("a",{attrs:{href:"https://chaincode.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Chaincode Labs"),t("OutboundLink")],1),e._v(" and then by "),t("a",{attrs:{href:"https://spiral.xyz/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spiral"),t("OutboundLink")],1),e._v(", LDK has gone from a good idea to a mature, "),t("a",{attrs:{href:"https://github.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("open-source project"),t("OutboundLink")],1),e._v(" with "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[e._v("many contributors"),t("OutboundLink")],1),e._v(" in just a few years. LDK is a robust, modular, mobile-friendly SDK that can be "),t("a",{attrs:{href:"https://vimeo.com/showcase/8372504/video/412818125",target:"_blank",rel:"noopener noreferrer"}},[e._v("integrated into existing bitcoin wallets"),t("OutboundLink")],1),e._v(" while significantly "),t("a",{attrs:{href:"https://bitcointv.com/w/sy6s9vVCmDvXr46YtbYcXM",target:"_blank",rel:"noopener noreferrer"}},[e._v("improving how developers integrate Lightning"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("Over time, we hope that LDK will become a public good that doesn’t rely on a single entity like Spiral to be sustainable, which is why we’re already fostering a community, empowering non-Spiral participants, and "),t("a",{attrs:{href:"https://spiral.xyz/blog/a-framework-for-sustainable-open-source-bitcoin-development/",target:"_blank",rel:"noopener noreferrer"}},[e._v("gradually reducing Spiral’s influence"),t("OutboundLink")],1),e._v(". Like Bitcoin Core, we expect LDK to have a strong group of volunteers contributing to the project and many entities funding the project.")]),e._v(" "),t("h2",{attrs:{id:"what-advantages-does-ldk-offer-developers"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-advantages-does-ldk-offer-developers"}},[e._v("#")]),e._v(" What advantages does LDK offer developers?")]),e._v(" "),t("p",[e._v("Before committing to LDK, we spoke with over 50 wallet developers to learn what challenges they faced. We learned that developing Lightning apps was a universally bad experience, especially in mobile environments, and that a small team of experienced engineers could take up to two years to build a basic Lightning application. So… not great.")]),e._v(" "),t("p",[e._v("LDK is a flexible Lightning implementation that focuses on running the Lightning node on a mobile phone in a non-custodial manner, which has significant privacy and sovereignty benefits. While this presents some technical challenges, non-custodial mobile apps are where LDK specializes, whether someone is building a wallet from scratch or integrating LDK into one that already exists.")]),e._v(" "),t("p",[e._v("Before LDK, if your team wanted to add Lightning functionality to a mobile app, you most likely had to modify and customize an existing implementation like LND to make it suitable for mobile devices. Core Lightning is also hard to run on iPhones. Both of these implementations are out-of-the-box node solutions that provide solid RPC and HTTP interfaces, but are targeted for server environments or simply aren’t suited to mobile.")]),e._v(" "),t("p",[e._v("Furthermore, if you want to turn your on-chain wallet into a unified wallet experience or source chain data from a third-party server using the Electrum protocol for resource-constrained devices, it’s complex, time-consuming, and a huge engineering undertaking.")]),e._v(" "),t("p",[e._v("Maintaining an LN implementation that you can trust with real money is challenging, and different needs exist for routing nodes and mobile nodes. Maintenance costs also increase over time due to ageing codebases, interactions with other layers, and new use cases with different performance and security trade-offs. We see this with "),t("a",{attrs:{href:"https://github.com/breez/breezmobile",target:"_blank",rel:"noopener noreferrer"}},[e._v("Breez"),t("OutboundLink")],1),e._v(" forking "),t("a",{attrs:{href:"https://github.com/breez/lnd",target:"_blank",rel:"noopener noreferrer"}},[e._v("LND"),t("OutboundLink")],1),e._v(" to make it suitable for mobile and ACINQ doing something similar with "),t("a",{attrs:{href:"https://github.com/ACINQ/phoenix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Phoenix"),t("OutboundLink")],1),e._v(" wallet and "),t("a",{attrs:{href:"https://github.com/ACINQ/lightning-kmp",target:"_blank",rel:"noopener noreferrer"}},[e._v("lightning-kmp"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We created LDK in multiple languages with an API-first approach designed to run at the application layer, like Rust’s "),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Persist"),t("OutboundLink")],1),e._v(" trait. Persist defines behaviour for persisting channel states but lets you specify whether you write this data to disk or another backup mechanism, such as the cloud. You don’t need to write an LN implementation from scratch or modify an existing one to use LN functionality. Just call our APIs from your app.")]),e._v(" "),t("p",[e._v("Finally (for this section), LDK’s flexibility enables several different architectures without sacrificing security. Its lightweight design can be optimized to run on embedded devices or HSMs (hardware security modules) and it doesn’t make system calls, so it can run in almost any OS environment. For example, you can opt to run some Lightning logic, such as signing transactions and updating channel states on an HSM that has specific "),t("a",{attrs:{href:"https://gitlab.com/lightning-signer/docs/-/blob/master/README.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("spending policies"),t("OutboundLink")],1),e._v(" and manages private keys. Then you connect it to a server with its own TCP/IP stack using a serial communication method such as USB.")]),e._v(" "),t("p",[e._v("Check out this "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=9-81tobFSKg",target:"_blank",rel:"noopener noreferrer"}},[e._v("presentation"),t("OutboundLink")],1),e._v(" at btc++ by "),t("a",{attrs:{href:"https://twitter.com/jkczyz",target:"_blank",rel:"noopener noreferrer"}},[e._v("Jeff Czyz"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://twitter.com/arikaleph",target:"_blank",rel:"noopener noreferrer"}},[e._v("Arik Sosman"),t("OutboundLink")],1),e._v(" to learn more about LDK "),t("a",{attrs:{href:"https://lightningdevkit.org/introduction/use_cases/",target:"_blank",rel:"noopener noreferrer"}},[e._v("use cases"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"who-uses-ldk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#who-uses-ldk"}},[e._v("#")]),e._v(" Who uses LDK?")]),e._v(" "),t("p",[e._v("LDK supports applications that require running many nodes (such as server/custodial apps), letting users run nodes on mobile devices, integrating with existing infrastructure, broad customization options, and resource-constrained embedded systems such as point of sale, IoT, and so on and so on, etc.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bluewallet.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("Blue Wallet"),t("OutboundLink")],1),e._v(" was LDK’s patient zero and ideal first adopter since it is both non-custodial and mobile. Their team maintains "),t("a",{attrs:{href:"https://github.com/BlueWallet/rn-ldk",target:"_blank",rel:"noopener noreferrer"}},[e._v("rn-ldk"),t("OutboundLink")],1),e._v(" and runs it on both Android and iOS.The wallet is likely to ship with LDK soon but not before some critical infrastructure is in place. While non-custodial mobile wallets are LDK’s primary use case, that doesn’t make it limited to them.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://cash.app",target:"_blank",rel:"noopener noreferrer"}},[e._v("CashApp"),t("OutboundLink")],1),e._v(", one of the world’s most used payment apps, chose LDK for its Lightning implementation because of its customizability. While custodial server-based solutions are not the primary use case for LDK, it shows how adaptable the library is. Ryan Loomba recently explained some of the trade-offs their team had to think about when comparing LDK to other solutions "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=kbhL5RqL8Aw",target:"_blank",rel:"noopener noreferrer"}},[e._v("at btc++"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://l2.technology/sensei",target:"_blank",rel:"noopener noreferrer"}},[e._v("Sensei"),t("OutboundLink")],1),e._v(", an out-of-the-box lightning node solution, is also powered by LDK. Its modular architecture enables a unique multi-node operation mode, letting nodes easily share a network graph, route scoring, and chain data which enables exciting new use cases.")]),e._v(" "),t("p",[e._v("We’re also talking to dozens of developers, some of whom we expect to adopt LDK soon.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions/1554",target:"_blank",rel:"noopener noreferrer"}},[e._v("Know someone building a Lightning wallet or related application?"),t("OutboundLink")],1),e._v(" Point them in "),t("a",{attrs:{href:"https://twitter.com/moneyball",target:"_blank",rel:"noopener noreferrer"}},[e._v("@moneyball’s"),t("OutboundLink")],1),e._v(" direction. If you’re already using LDK and have questions, hop into our "),t("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discord"),t("OutboundLink")],1),e._v(" or checkout GitHub "),t("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discussions"),t("OutboundLink")],1)]),e._v(" "),t("h2",{attrs:{id:"what-are-ldk-s-engineering-priorities"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-are-ldk-s-engineering-priorities"}},[e._v("#")]),e._v(" What are LDK’s engineering priorities?")]),e._v(" "),t("p",[t("code",[e._v("Offline Receive")]),t("br"),e._v("\nA problem with Lightning UX is that mobile wallets can’t receive payments unless the user is using the app. We’re developing solutions in conjunction with the LN developer community that will let offline nodes receive payments. Spiral’s Matt Corallo has a "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("pull request"),t("OutboundLink")],1),e._v(" open that proposes a protocol to fix this exact problem. It includes his original post to the Lightning Devs mailing list which is a "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("pretty good technical"),t("OutboundLink")],1),e._v(" read on this issue if you’re in the mood for one of those.")]),e._v(" "),t("p",[t("code",[e._v("BOLT 12")]),t("br"),e._v("\nThis feature improves privacy by allowing reusable payments over blinded paths and provides a framework for future upgrades that support recurring payments. There’s still work to be done, and it includes implementing route blinding/blinded paths, an onion messages API for requesting invoices, and BOLT 12 invoice parsing.")]),e._v(" "),t("p",[t("code",[e._v("Taproot")]),t("br"),e._v("\nTaproot! People love it. We love it. It’s been several months since full activation, and LDK will start to take advantage of everything it offers. This includes improved on-chain privacy by making current funding channel outputs (2-of-2 multisig) indistinguishable from single sig outputs, and making channel opening and closing transactions look more like regular non-lightning transactions. In addition, we’re looking to support multi-sig channel capabilities as they allow for greater security, redundancy, and flexibility.")]),e._v(" "),t("p",[t("code",[e._v("Language Bindings")]),t("br"),e._v("\nWe’re making existing language integrations feel more native. We currently support Rust, C/C++, Swift, Java, & Kotlin. It’s now in the beta stage, but "),t("a",{attrs:{href:"https://www.npmjs.com/package/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("JavaScript/TypeScript/Wasm"),t("OutboundLink")],1),e._v(" is also supported, and we are prioritizing bug fixing for early adopters. In the future, expect support for C#, Python, Flutter/Dart, and possibly others.")]),e._v(" "),t("p",[e._v("Also in LDK’s future: a simplified API that makes opinionated decisions on behalf of developers that will accelerate getting their apps up and running. Think of it as a Rust crate but using UniFFI to auto-generate language bindings for Kotlin, Swift, Python, and Ruby that expedite basic send/receive functionality.")]),e._v(" "),t("h2",{attrs:{id:"notable-updates"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#notable-updates"}},[e._v("#")]),e._v(" Notable Updates")]),e._v(" "),t("p",[e._v("Phantom Node support is up and running (separate blog post coming soon…ish). This integration adds support for multi-node receive, which enables enterprise-level architecture. This is important since users might need production nodes to receive payments when load balancing is required.")]),e._v(" "),t("p",[e._v("We've introduced a new client-side pathfinding API to LDK that simplifies quickly downloading gossip data from a server. This means that servers can't know who you are paying or how much.")]),e._v(" "),t("p",[e._v("We now support zero conf channels, allowing immediate forwarding of payments after channel opening/receiving for those wanting to build inbound liquidity services.")]),e._v(" "),t("p",[e._v("SCID Aliases (short channel IDs) were added in a recent release and may be negotiated when opening a channel with a peer. This has significant privacy benefits and will likely be the default in the future.")]),e._v(" "),t("p",[e._v("Anything else?")]),e._v(" "),t("p",[e._v("Absolutely. But this post is long enough for now. Keep an eye out for announcements from "),t("a",{attrs:{href:"https://twitter.com/spiralbtc",target:"_blank",rel:"noopener noreferrer"}},[e._v("@spiralbtc"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://twitter.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("@lightningdevkit"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{392:function(e,t,n){"use strict";n.r(t);var i=n(7),r=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("We are excited to release our first blog post, we have a lot to share and a lot to build. We’ll be updating this blog regularly with what we’re working on, new features and the details on new releases.")]),e._v(" "),t("h2",{attrs:{id:"ldwho"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldwho"}},[e._v("#")]),e._v(" LDWho?")]),e._v(" "),t("p",[e._v("If you’re reading this, you probably know something about the Lightning Development Kit, the easy-to-use open-source tool that simplifies how developers add highly secure, privacy-preserving Lightning functionality to bitcoin applications. What you might not know is how it got started.")]),e._v(" "),t("p",[e._v("LDK began as a side project developed by Matt Corallo "),t("a",{attrs:{href:"https://twitter.com/TheBlueMatt",target:"_blank",rel:"noopener noreferrer"}},[e._v("@TheBlueMatt"),t("OutboundLink")],1),e._v(" in "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/commit/6185a2819090bd077954244c5e2adaab5efcaa1a",target:"_blank",rel:"noopener noreferrer"}},[e._v("2018"),t("OutboundLink")],1),e._v(" called rust-lightning. One of Matt’s earliest rust-lightning "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=bfAz0vYlDAI",target:"_blank",rel:"noopener noreferrer"}},[e._v("demos"),t("OutboundLink")],1),e._v(" shows how you can take a full Lightning implementation (managing channels, generating messages to send to peers, signatures, on-chain punishment, etc), and use it to create a library with high-level APIs, so developers can build more and agonize less.")]),e._v(" "),t("p",[e._v("This highly specialized library needed to be flexible enough to let developers customize areas like on-chain wallet creation, sourcing blockchain data, and backing up channel states while paving the way for them to make those critical decisions at 10x speed.")]),e._v(" "),t("p",[e._v("Initially supported by "),t("a",{attrs:{href:"https://chaincode.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Chaincode Labs"),t("OutboundLink")],1),e._v(" and then by "),t("a",{attrs:{href:"https://spiral.xyz/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spiral"),t("OutboundLink")],1),e._v(", LDK has gone from a good idea to a mature, "),t("a",{attrs:{href:"https://github.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("open-source project"),t("OutboundLink")],1),e._v(" with "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/graphs/contributors",target:"_blank",rel:"noopener noreferrer"}},[e._v("many contributors"),t("OutboundLink")],1),e._v(" in just a few years. LDK is a robust, modular, mobile-friendly SDK that can be "),t("a",{attrs:{href:"https://vimeo.com/showcase/8372504/video/412818125",target:"_blank",rel:"noopener noreferrer"}},[e._v("integrated into existing bitcoin wallets"),t("OutboundLink")],1),e._v(" while significantly "),t("a",{attrs:{href:"https://bitcointv.com/w/sy6s9vVCmDvXr46YtbYcXM",target:"_blank",rel:"noopener noreferrer"}},[e._v("improving how developers integrate Lightning"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("Over time, we hope that LDK will become a public good that doesn’t rely on a single entity like Spiral to be sustainable, which is why we’re already fostering a community, empowering non-Spiral participants, and "),t("a",{attrs:{href:"https://spiral.xyz/blog/a-framework-for-sustainable-open-source-bitcoin-development/",target:"_blank",rel:"noopener noreferrer"}},[e._v("gradually reducing Spiral’s influence"),t("OutboundLink")],1),e._v(". Like Bitcoin Core, we expect LDK to have a strong group of volunteers contributing to the project and many entities funding the project.")]),e._v(" "),t("h2",{attrs:{id:"what-advantages-does-ldk-offer-developers"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-advantages-does-ldk-offer-developers"}},[e._v("#")]),e._v(" What advantages does LDK offer developers?")]),e._v(" "),t("p",[e._v("Before committing to LDK, we spoke with over 50 wallet developers to learn what challenges they faced. We learned that developing Lightning apps was a universally bad experience, especially in mobile environments, and that a small team of experienced engineers could take up to two years to build a basic Lightning application. So… not great.")]),e._v(" "),t("p",[e._v("LDK is a flexible Lightning implementation that focuses on running the Lightning node on a mobile phone in a non-custodial manner, which has significant privacy and sovereignty benefits. While this presents some technical challenges, non-custodial mobile apps are where LDK specializes, whether someone is building a wallet from scratch or integrating LDK into one that already exists.")]),e._v(" "),t("p",[e._v("Before LDK, if your team wanted to add Lightning functionality to a mobile app, you most likely had to modify and customize an existing implementation like LND to make it suitable for mobile devices. Core Lightning is also hard to run on iPhones. Both of these implementations are out-of-the-box node solutions that provide solid RPC and HTTP interfaces, but are targeted for server environments or simply aren’t suited to mobile.")]),e._v(" "),t("p",[e._v("Furthermore, if you want to turn your on-chain wallet into a unified wallet experience or source chain data from a third-party server using the Electrum protocol for resource-constrained devices, it’s complex, time-consuming, and a huge engineering undertaking.")]),e._v(" "),t("p",[e._v("Maintaining an LN implementation that you can trust with real money is challenging, and different needs exist for routing nodes and mobile nodes. Maintenance costs also increase over time due to ageing codebases, interactions with other layers, and new use cases with different performance and security trade-offs. We see this with "),t("a",{attrs:{href:"https://github.com/breez/breezmobile",target:"_blank",rel:"noopener noreferrer"}},[e._v("Breez"),t("OutboundLink")],1),e._v(" forking "),t("a",{attrs:{href:"https://github.com/breez/lnd",target:"_blank",rel:"noopener noreferrer"}},[e._v("LND"),t("OutboundLink")],1),e._v(" to make it suitable for mobile and ACINQ doing something similar with "),t("a",{attrs:{href:"https://github.com/ACINQ/phoenix",target:"_blank",rel:"noopener noreferrer"}},[e._v("Phoenix"),t("OutboundLink")],1),e._v(" wallet and "),t("a",{attrs:{href:"https://github.com/ACINQ/lightning-kmp",target:"_blank",rel:"noopener noreferrer"}},[e._v("lightning-kmp"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We created LDK in multiple languages with an API-first approach designed to run at the application layer, like Rust’s "),t("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Persist"),t("OutboundLink")],1),e._v(" trait. Persist defines behaviour for persisting channel states but lets you specify whether you write this data to disk or another backup mechanism, such as the cloud. You don’t need to write an LN implementation from scratch or modify an existing one to use LN functionality. Just call our APIs from your app.")]),e._v(" "),t("p",[e._v("Finally (for this section), LDK’s flexibility enables several different architectures without sacrificing security. Its lightweight design can be optimized to run on embedded devices or HSMs (hardware security modules) and it doesn’t make system calls, so it can run in almost any OS environment. For example, you can opt to run some Lightning logic, such as signing transactions and updating channel states on an HSM that has specific "),t("a",{attrs:{href:"https://gitlab.com/lightning-signer/docs/-/blob/master/README.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("spending policies"),t("OutboundLink")],1),e._v(" and manages private keys. Then you connect it to a server with its own TCP/IP stack using a serial communication method such as USB.")]),e._v(" "),t("p",[e._v("Check out this "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=9-81tobFSKg",target:"_blank",rel:"noopener noreferrer"}},[e._v("presentation"),t("OutboundLink")],1),e._v(" at btc++ by "),t("a",{attrs:{href:"https://twitter.com/jkczyz",target:"_blank",rel:"noopener noreferrer"}},[e._v("Jeff Czyz"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://twitter.com/arikaleph",target:"_blank",rel:"noopener noreferrer"}},[e._v("Arik Sosman"),t("OutboundLink")],1),e._v(" to learn more about LDK "),t("a",{attrs:{href:"https://lightningdevkit.org/introduction/use_cases/",target:"_blank",rel:"noopener noreferrer"}},[e._v("use cases"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"who-uses-ldk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#who-uses-ldk"}},[e._v("#")]),e._v(" Who uses LDK?")]),e._v(" "),t("p",[e._v("LDK supports applications that require running many nodes (such as server/custodial apps), letting users run nodes on mobile devices, integrating with existing infrastructure, broad customization options, and resource-constrained embedded systems such as point of sale, IoT, and so on and so on, etc.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bluewallet.io",target:"_blank",rel:"noopener noreferrer"}},[e._v("Blue Wallet"),t("OutboundLink")],1),e._v(" was LDK’s patient zero and ideal first adopter since it is both non-custodial and mobile. Their team maintains "),t("a",{attrs:{href:"https://github.com/BlueWallet/rn-ldk",target:"_blank",rel:"noopener noreferrer"}},[e._v("rn-ldk"),t("OutboundLink")],1),e._v(" and runs it on both Android and iOS.The wallet is likely to ship with LDK soon but not before some critical infrastructure is in place. While non-custodial mobile wallets are LDK’s primary use case, that doesn’t make it limited to them.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://cash.app",target:"_blank",rel:"noopener noreferrer"}},[e._v("CashApp"),t("OutboundLink")],1),e._v(", one of the world’s most used payment apps, chose LDK for its Lightning implementation because of its customizability. While custodial server-based solutions are not the primary use case for LDK, it shows how adaptable the library is. Ryan Loomba recently explained some of the trade-offs their team had to think about when comparing LDK to other solutions "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=kbhL5RqL8Aw",target:"_blank",rel:"noopener noreferrer"}},[e._v("at btc++"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://l2.technology/sensei",target:"_blank",rel:"noopener noreferrer"}},[e._v("Sensei"),t("OutboundLink")],1),e._v(", an out-of-the-box lightning node solution, is also powered by LDK. Its modular architecture enables a unique multi-node operation mode, letting nodes easily share a network graph, route scoring, and chain data which enables exciting new use cases.")]),e._v(" "),t("p",[e._v("We’re also talking to dozens of developers, some of whom we expect to adopt LDK soon.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions/1554",target:"_blank",rel:"noopener noreferrer"}},[e._v("Know someone building a Lightning wallet or related application?"),t("OutboundLink")],1),e._v(" Point them in "),t("a",{attrs:{href:"https://twitter.com/moneyball",target:"_blank",rel:"noopener noreferrer"}},[e._v("@moneyball’s"),t("OutboundLink")],1),e._v(" direction. If you’re already using LDK and have questions, hop into our "),t("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discord"),t("OutboundLink")],1),e._v(" or checkout GitHub "),t("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions",target:"_blank",rel:"noopener noreferrer"}},[e._v("Discussions"),t("OutboundLink")],1)]),e._v(" "),t("h2",{attrs:{id:"what-are-ldk-s-engineering-priorities"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-are-ldk-s-engineering-priorities"}},[e._v("#")]),e._v(" What are LDK’s engineering priorities?")]),e._v(" "),t("p",[t("code",[e._v("Offline Receive")]),t("br"),e._v("\nA problem with Lightning UX is that mobile wallets can’t receive payments unless the user is using the app. We’re developing solutions in conjunction with the LN developer community that will let offline nodes receive payments. Spiral’s Matt Corallo has a "),t("a",{attrs:{href:"https://github.com/lightning/bolts/pull/989",target:"_blank",rel:"noopener noreferrer"}},[e._v("pull request"),t("OutboundLink")],1),e._v(" open that proposes a protocol to fix this exact problem. It includes his original post to the Lightning Devs mailing list which is a "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("pretty good technical"),t("OutboundLink")],1),e._v(" read on this issue if you’re in the mood for one of those.")]),e._v(" "),t("p",[t("code",[e._v("BOLT 12")]),t("br"),e._v("\nThis feature improves privacy by allowing reusable payments over blinded paths and provides a framework for future upgrades that support recurring payments. There’s still work to be done, and it includes implementing route blinding/blinded paths, an onion messages API for requesting invoices, and BOLT 12 invoice parsing.")]),e._v(" "),t("p",[t("code",[e._v("Taproot")]),t("br"),e._v("\nTaproot! People love it. We love it. It’s been several months since full activation, and LDK will start to take advantage of everything it offers. This includes improved on-chain privacy by making current funding channel outputs (2-of-2 multisig) indistinguishable from single sig outputs, and making channel opening and closing transactions look more like regular non-lightning transactions. In addition, we’re looking to support multi-sig channel capabilities as they allow for greater security, redundancy, and flexibility.")]),e._v(" "),t("p",[t("code",[e._v("Language Bindings")]),t("br"),e._v("\nWe’re making existing language integrations feel more native. We currently support Rust, C/C++, Swift, Java, & Kotlin. It’s now in the beta stage, but "),t("a",{attrs:{href:"https://www.npmjs.com/package/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("JavaScript/TypeScript/Wasm"),t("OutboundLink")],1),e._v(" is also supported, and we are prioritizing bug fixing for early adopters. In the future, expect support for C#, Python, Flutter/Dart, and possibly others.")]),e._v(" "),t("p",[e._v("Also in LDK’s future: a simplified API that makes opinionated decisions on behalf of developers that will accelerate getting their apps up and running. Think of it as a Rust crate but using UniFFI to auto-generate language bindings for Kotlin, Swift, Python, and Ruby that expedite basic send/receive functionality.")]),e._v(" "),t("h2",{attrs:{id:"notable-updates"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#notable-updates"}},[e._v("#")]),e._v(" Notable Updates")]),e._v(" "),t("p",[e._v("Phantom Node support is up and running (separate blog post coming soon…ish). This integration adds support for multi-node receive, which enables enterprise-level architecture. This is important since users might need production nodes to receive payments when load balancing is required.")]),e._v(" "),t("p",[e._v("We've introduced a new client-side pathfinding API to LDK that simplifies quickly downloading gossip data from a server. This means that servers can't know who you are paying or how much.")]),e._v(" "),t("p",[e._v("We now support zero conf channels, allowing immediate forwarding of payments after channel opening/receiving for those wanting to build inbound liquidity services.")]),e._v(" "),t("p",[e._v("SCID Aliases (short channel IDs) were added in a recent release and may be negotiated when opening a channel with a peer. This has significant privacy benefits and will likely be the default in the future.")]),e._v(" "),t("p",[e._v("Anything else?")]),e._v(" "),t("p",[e._v("Absolutely. But this post is long enough for now. Keep an eye out for announcements from "),t("a",{attrs:{href:"https://twitter.com/spiralbtc",target:"_blank",rel:"noopener noreferrer"}},[e._v("@spiralbtc"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://twitter.com/lightningdevkit",target:"_blank",rel:"noopener noreferrer"}},[e._v("@lightningdevkit"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/32.ca5b8d56.js b/assets/js/33.ad075210.js similarity index 98% rename from assets/js/32.ca5b8d56.js rename to assets/js/33.ad075210.js index caf6fd3d9..2aeb91a4b 100644 --- a/assets/js/32.ca5b8d56.js +++ b/assets/js/33.ad075210.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{390:function(e,t,n){"use strict";n.r(t);var i=n(7),a=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Mutiny is a new lightning wallet for the web. It is the first self-custodial wallet to run directly in a user's browser. It’s built on top of LDK and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(", written in Rust, and compiled into WebAssembly. It offers a simple, intuitive interface for sending and receiving payments and other advanced features, such as Nostr Wallet Connect and subscription payments.")]),e._v(" "),t("p",[e._v("We chose to build on LDK and BDK because it wouldn’t have been possible to build a wallet like Mutiny in any other way. Since LDK is written in Rust, we were able to compile it into WebAssembly. Rust's unique combination of type-safety, memory-safety, and efficient runtime performance make it ideally suited to a lightning node that must be reliable, fast, and lightweight enough to run on a mobile phone. LDK's modular design means we can customize it to work within the specific constraints of a web browser. LDK also provides a robust API for building advanced features for our wallet that would otherwise not be possible.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),t("p",[e._v("We used LDK to make a crate called mutiny-node which holds all our main wallet logic. Then we used the wasm-bindgencrate to generate JavaScript bindings that can be imported into a regular web project. Thankfully, LDK supports no_std, so compiling it into WebAssembly without any modifications was possible.")]),e._v(" "),t("p",[e._v("Mutiny is a lite-client wallet, meaning it does not run a full bitcoin node. Instead, it gets its blockchain data from an esplora instance. LDK's Filter interface made it easy to implement this, allowing for a simple and efficient way to sync the wallet with the blockchain. "),t("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/0.0.115/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync"),t("OutboundLink")],1),e._v(" also helps make the wallet sync quickly, and RGS allows us to sync lightning gossip data nearly instantly without spending unnecessary bandwidth and CPU resources.")]),e._v(" "),t("p",[e._v("Local storage can be unreliable in web browsers, so we also want users to be able to recover their wallet in case they lose their device. We implemented the LDK project's "),t("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[e._v("VSS"),t("OutboundLink")],1),e._v(" specification to give our users encrypted cloud backups to support this.")]),e._v(" "),t("p",[e._v("While we're currently focused on the web, this architecture and the flexibility of LDK means we will be able to share most of our code with a mobile or even server version of Mutiny in the future.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("LDK made building a lightning wallet that runs in the browser possible. Compiling to WebAssembly and LDK's various tools for lite clients allowed us to create an unstoppable, self-custodial wallet that anyone can use without downloading any software. We hope that Mutiny will help bring lightning to the masses, and we are excited to see what the future holds for LDK and lightning on the web.")]),e._v(" "),t("p",[e._v("You can learn more and try it out at "),t("a",{attrs:{href:"https://www.mutinywallet.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("mutinywallet.com"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{394:function(e,t,n){"use strict";n.r(t);var i=n(7),a=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Mutiny is a new lightning wallet for the web. It is the first self-custodial wallet to run directly in a user's browser. It’s built on top of LDK and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(", written in Rust, and compiled into WebAssembly. It offers a simple, intuitive interface for sending and receiving payments and other advanced features, such as Nostr Wallet Connect and subscription payments.")]),e._v(" "),t("p",[e._v("We chose to build on LDK and BDK because it wouldn’t have been possible to build a wallet like Mutiny in any other way. Since LDK is written in Rust, we were able to compile it into WebAssembly. Rust's unique combination of type-safety, memory-safety, and efficient runtime performance make it ideally suited to a lightning node that must be reliable, fast, and lightweight enough to run on a mobile phone. LDK's modular design means we can customize it to work within the specific constraints of a web browser. LDK also provides a robust API for building advanced features for our wallet that would otherwise not be possible.")]),e._v(" "),t("h1",{attrs:{id:"what-we-did"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-we-did"}},[e._v("#")]),e._v(" What we did?")]),e._v(" "),t("p",[e._v("We used LDK to make a crate called mutiny-node which holds all our main wallet logic. Then we used the wasm-bindgencrate to generate JavaScript bindings that can be imported into a regular web project. Thankfully, LDK supports no_std, so compiling it into WebAssembly without any modifications was possible.")]),e._v(" "),t("p",[e._v("Mutiny is a lite-client wallet, meaning it does not run a full bitcoin node. Instead, it gets its blockchain data from an esplora instance. LDK's Filter interface made it easy to implement this, allowing for a simple and efficient way to sync the wallet with the blockchain. "),t("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/0.0.115/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rapid Gossip Sync"),t("OutboundLink")],1),e._v(" also helps make the wallet sync quickly, and RGS allows us to sync lightning gossip data nearly instantly without spending unnecessary bandwidth and CPU resources.")]),e._v(" "),t("p",[e._v("Local storage can be unreliable in web browsers, so we also want users to be able to recover their wallet in case they lose their device. We implemented the LDK project's "),t("a",{attrs:{href:"https://github.com/lightningdevkit/vss-server",target:"_blank",rel:"noopener noreferrer"}},[e._v("VSS"),t("OutboundLink")],1),e._v(" specification to give our users encrypted cloud backups to support this.")]),e._v(" "),t("p",[e._v("While we're currently focused on the web, this architecture and the flexibility of LDK means we will be able to share most of our code with a mobile or even server version of Mutiny in the future.")]),e._v(" "),t("h1",{attrs:{id:"results"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#results"}},[e._v("#")]),e._v(" Results")]),e._v(" "),t("p",[e._v("LDK made building a lightning wallet that runs in the browser possible. Compiling to WebAssembly and LDK's various tools for lite clients allowed us to create an unstoppable, self-custodial wallet that anyone can use without downloading any software. We hope that Mutiny will help bring lightning to the masses, and we are excited to see what the future holds for LDK and lightning on the web.")]),e._v(" "),t("p",[e._v("You can learn more and try it out at "),t("a",{attrs:{href:"https://www.mutinywallet.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("mutinywallet.com"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/33.bc0dc9bd.js b/assets/js/34.f706fbc9.js similarity index 99% rename from assets/js/33.bc0dc9bd.js rename to assets/js/34.f706fbc9.js index 3b111a4d3..feceec639 100644 --- a/assets/js/33.bc0dc9bd.js +++ b/assets/js/34.f706fbc9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{393:function(e,t,n){"use strict";n.r(t);var i=n(7),o=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Lightning development is tough. While going custodial simplifies the process, it means sacrificing user privacy, censorship resistance, and self-sovereignty, all of which contradict bitcoin’s ethos. Therefore, many companies and projects have started with or redirected their focus from building custodial to non-custodial Lightning applications.")]),e._v(" "),t("h2",{attrs:{id:"obstacles"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#obstacles"}},[e._v("#")]),e._v(" Obstacles")]),e._v(" "),t("p",[e._v("There are several basic requirements for wallets wanting to add Lightning capabilities, such as connecting to the Lightning Network via a Lightning Implementation, syncing with on-chain transactions, and opening and closing channels. When building a mobile application, developers face additional technical challenges:")]),e._v(" "),t("h2",{attrs:{id:"liquidity"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#liquidity"}},[e._v("#")]),e._v(" Liquidity")]),e._v(" "),t("p",[e._v("To receive funds via Lightning, someone must have on-chain bitcoin locked up in a channel. Transaction completion is delayed if the receiver has an empty or insufficient channel balance. For example, let’s say that someone has 50,000 sats of inbound liquidity and is trying to receive 100,000 sats. Before the Lightning transaction can be initiated, additional liquidity is required to cover the 100,000 sats total plus fees from channel reserves and anchor outputs, which are mechanisms to improve security. This is done via on-chain transactions, which come with fees.")]),e._v(" "),t("p",[e._v("Additionally, on-chain transactions must be mined into multiple blocks before being confirmed. It’s not a great user experience if someone has to do work upfront and wait roughly 30–60 minutes before they can send or receive money.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://lightningdevkit.org/blog/zero-confirmation-channels/",target:"_blank",rel:"noopener noreferrer"}},[e._v("0-conf"),t("OutboundLink")],1),e._v(" channels offer a partial solution, allowing users to receive Lightning instantly. 0-conf enables the client to trust their channel counterparty (usually an application vendor or partner) for a limited time until an on-chain transaction is confirmed. While this helps with speed, the fact that 0conf channels require some level of trust is a trade-off.")]),e._v(" "),t("p",[e._v("Liquidity Service Providers (LSPs) provide liquidity upfront through automated channel and liquidity management. LSPs supply more liquidity than required for immediate payments rather than the exact amount to ensure that remaining funds are in the channel for future transactions. If a user conducts multiple payments, it’s best to avoid doing on-chain transactions for every Lightning transaction.")]),e._v(" "),t("p",[e._v("LSPs do not want to pay excessive on-chain fees, but it’s hard to predict how often people will send and receive transactions and for how much. Therefore, there’s no straightforward way to know how much liquidity should be locked into a given channel. LSPs have to determine how much money they can contribute and how much it'll cost. This can be anywhere from aggressive (locking up a generous amount) to conservative (locking up a small amount). Ultimately, this decision results in a “compression ratio,\" i.e., the number of on-chain transactions required per Lightning transaction. Some very conservative LSPs may get a compression ratio close to one, saving their users relatively little on fees, but there is nearly always some gain to be had in using Lightning over on-chain.")]),e._v(" "),t("p",[e._v("While predicting what the compression ratio should be remains a major challenge, most solutions today offer some compression information, allowing us to learn and improve. For this reason, it’s worth deploying Lightning for instant transactions at lower costs compared to on-chain, even if it's not as common as it could be. We expect this to get better over time.")]),e._v(" "),t("h1",{attrs:{id:"receive-wakeup"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#receive-wakeup"}},[e._v("#")]),e._v(" Receive Wakeup")]),e._v(" "),t("p",[e._v("Lightning requires nodes (or, specifically, their cryptographic keys) to be online to exchange signatures and complete payments, meaning the user must be on their phone and with service. Receiving wakeups is problematic because incomplete payments are not great for the Lightning Network—it’s detrimental to keep the money for a payment locked up until someone comes back online.")]),e._v(" "),t("p",[e._v("iOS and Android operating systems help address this problem by allowing a small amount of code to run when notifications are received, even if the relevant application isn’t open. However, suppose an application is infrequently used or the device has a low battery. In that case, the application will often not get any CPU time, resulting in the payment being stuck until the user opens the app.")]),e._v(" "),t("p",[e._v("A lot of work must be done to make it possible for senders and recipients to exchange payments asynchronously, "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307",target:"_blank",rel:"noopener noreferrer"}},[e._v("but a protocol sketch is in the works"),t("OutboundLink")],1),e._v(". You can find a more detailed explainer "),t("a",{attrs:{href:"https://gist.github.com/remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h1",{attrs:{id:"live-backups"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#live-backups"}},[e._v("#")]),e._v(" Live Backups")]),e._v(" "),t("p",[e._v("These are especially problematic when a user has to reinstall an application or loses their phone. In addition to needing their seed phrase, they’ll need the latest Lightning state data stored on their device to get their money back reliably.")]),e._v(" "),t("p",[e._v("The Lightning state changes every time a user sends or receives money, so backups must be frequently updated on a server. While some devices use Google Drive or iCloud, those protocols sync asynchronously, often leading to data being out of sync. Cloud methods sanitize data stored on the client well, but they may not ensure reliable full funds recovery if a device is lost.")]),e._v(" "),t("p",[e._v("Advanced versions of live online sync allow users to open the same wallet on multiple devices. Users often do this despite it being challenging to do with Lightning applications since two devices running simultaneously can result in losing funds.")]),e._v(" "),t("h1",{attrs:{id:"privacy-preserving-payment-routing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#privacy-preserving-payment-routing"}},[e._v("#")]),e._v(" Privacy-preserving Payment Routing")]),e._v(" "),t("p",[e._v("Another commonly discussed issue is payment routing through the Lightning Network. This isn't easy because the route finder has to have some history of liquidity on the Lightning Network.")]),e._v(" "),t("p",[e._v("The most common method is to rely on a server for route-finding, which sees users' payment history and therefore compromises privacy. This may also pose long-term regulatory concerns for apps relying on such servers.")]),e._v(" "),t("p",[e._v("Without a server, the client needs to download the full Lightning graph. This can be slow and performance-compromising. Worse, the Lightning graph alone doesn’t provide enough information to achieve reliable payment success, leading to the possibility that transactions may take a long time to complete, or not go through at all.")]),e._v(" "),t("p",[e._v("To achieve better payment success, the client must send lots of payments, which can be done via probing (fake payments). Probing trains data on the network graph from a client's perspective and builds up a history of liquidity on the network. While this offers a solution, probing must be done consistently, requiring the client to be online 24/7. This could instead be done by an LSP, which can offer the resulting data to clients. Additionally, information is not super portable across LSPs, so each LSP needs to do its own probing.")]),e._v(" "),t("h1",{attrs:{id:"privacy-preserving-block-fetching"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#privacy-preserving-block-fetching"}},[e._v("#")]),e._v(" Privacy-preserving Block Fetching")]),e._v(" "),t("p",[e._v("For users to see their transaction history and balance, bitcoin and Lightning wallets need to connect to and download the blockchain. Each block contains a lot of data, making downloading the full blockchain on mobile devices impractical due to bandwidth constraints.")]),e._v(" "),t("p",[e._v("The most common way to obtain blockchain data is to connect to a server using Electrum or Esplora. To do this and get the relevant information, the client has to provide their user’s list of addresses, exposing transaction histories and balances.")]),e._v(" "),t("p",[e._v("It’s difficult to fetch blockchain data without giving up privacy. One way around this is to use compact block filters, which download data from a full node and only download a select amount of blocks. While compact block filters offer better privacy than a server and are more efficient than downloading the entire blockchain, the method isn’t perfect. Compact block filters are slow to sync and still require substantial bandwidth on the user’s device, making it a less enticing tradeoff for many wallets.")]),e._v(" "),t("p",[e._v("A third option, called private information retrieval, is more future-looking. This method is efficient for clients but expensive on the server side.")]),e._v(" "),t("h1",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("There are many obstacles to making non-custodial Lightning work privately on mobile devices, but it is doable. It requires a mobile-focused LN implementation, SDK, and infrastructure operated by an LSP or the application vendor. None of that needs to compromise user privacy or self-sovereignty, even though, in many designs, it does.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{398:function(e,t,n){"use strict";n.r(t);var i=n(7),o=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Lightning development is tough. While going custodial simplifies the process, it means sacrificing user privacy, censorship resistance, and self-sovereignty, all of which contradict bitcoin’s ethos. Therefore, many companies and projects have started with or redirected their focus from building custodial to non-custodial Lightning applications.")]),e._v(" "),t("h2",{attrs:{id:"obstacles"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#obstacles"}},[e._v("#")]),e._v(" Obstacles")]),e._v(" "),t("p",[e._v("There are several basic requirements for wallets wanting to add Lightning capabilities, such as connecting to the Lightning Network via a Lightning Implementation, syncing with on-chain transactions, and opening and closing channels. When building a mobile application, developers face additional technical challenges:")]),e._v(" "),t("h2",{attrs:{id:"liquidity"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#liquidity"}},[e._v("#")]),e._v(" Liquidity")]),e._v(" "),t("p",[e._v("To receive funds via Lightning, someone must have on-chain bitcoin locked up in a channel. Transaction completion is delayed if the receiver has an empty or insufficient channel balance. For example, let’s say that someone has 50,000 sats of inbound liquidity and is trying to receive 100,000 sats. Before the Lightning transaction can be initiated, additional liquidity is required to cover the 100,000 sats total plus fees from channel reserves and anchor outputs, which are mechanisms to improve security. This is done via on-chain transactions, which come with fees.")]),e._v(" "),t("p",[e._v("Additionally, on-chain transactions must be mined into multiple blocks before being confirmed. It’s not a great user experience if someone has to do work upfront and wait roughly 30–60 minutes before they can send or receive money.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://lightningdevkit.org/blog/zero-confirmation-channels/",target:"_blank",rel:"noopener noreferrer"}},[e._v("0-conf"),t("OutboundLink")],1),e._v(" channels offer a partial solution, allowing users to receive Lightning instantly. 0-conf enables the client to trust their channel counterparty (usually an application vendor or partner) for a limited time until an on-chain transaction is confirmed. While this helps with speed, the fact that 0conf channels require some level of trust is a trade-off.")]),e._v(" "),t("p",[e._v("Liquidity Service Providers (LSPs) provide liquidity upfront through automated channel and liquidity management. LSPs supply more liquidity than required for immediate payments rather than the exact amount to ensure that remaining funds are in the channel for future transactions. If a user conducts multiple payments, it’s best to avoid doing on-chain transactions for every Lightning transaction.")]),e._v(" "),t("p",[e._v("LSPs do not want to pay excessive on-chain fees, but it’s hard to predict how often people will send and receive transactions and for how much. Therefore, there’s no straightforward way to know how much liquidity should be locked into a given channel. LSPs have to determine how much money they can contribute and how much it'll cost. This can be anywhere from aggressive (locking up a generous amount) to conservative (locking up a small amount). Ultimately, this decision results in a “compression ratio,\" i.e., the number of on-chain transactions required per Lightning transaction. Some very conservative LSPs may get a compression ratio close to one, saving their users relatively little on fees, but there is nearly always some gain to be had in using Lightning over on-chain.")]),e._v(" "),t("p",[e._v("While predicting what the compression ratio should be remains a major challenge, most solutions today offer some compression information, allowing us to learn and improve. For this reason, it’s worth deploying Lightning for instant transactions at lower costs compared to on-chain, even if it's not as common as it could be. We expect this to get better over time.")]),e._v(" "),t("h1",{attrs:{id:"receive-wakeup"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#receive-wakeup"}},[e._v("#")]),e._v(" Receive Wakeup")]),e._v(" "),t("p",[e._v("Lightning requires nodes (or, specifically, their cryptographic keys) to be online to exchange signatures and complete payments, meaning the user must be on their phone and with service. Receiving wakeups is problematic because incomplete payments are not great for the Lightning Network—it’s detrimental to keep the money for a payment locked up until someone comes back online.")]),e._v(" "),t("p",[e._v("iOS and Android operating systems help address this problem by allowing a small amount of code to run when notifications are received, even if the relevant application isn’t open. However, suppose an application is infrequently used or the device has a low battery. In that case, the application will often not get any CPU time, resulting in the payment being stuck until the user opens the app.")]),e._v(" "),t("p",[e._v("A lot of work must be done to make it possible for senders and recipients to exchange payments asynchronously, "),t("a",{attrs:{href:"https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003307",target:"_blank",rel:"noopener noreferrer"}},[e._v("but a protocol sketch is in the works"),t("OutboundLink")],1),e._v(". You can find a more detailed explainer "),t("a",{attrs:{href:"https://gist.github.com/remyers/e0d2bedb7bc87371d1bdbbb6fff2edd1",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h1",{attrs:{id:"live-backups"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#live-backups"}},[e._v("#")]),e._v(" Live Backups")]),e._v(" "),t("p",[e._v("These are especially problematic when a user has to reinstall an application or loses their phone. In addition to needing their seed phrase, they’ll need the latest Lightning state data stored on their device to get their money back reliably.")]),e._v(" "),t("p",[e._v("The Lightning state changes every time a user sends or receives money, so backups must be frequently updated on a server. While some devices use Google Drive or iCloud, those protocols sync asynchronously, often leading to data being out of sync. Cloud methods sanitize data stored on the client well, but they may not ensure reliable full funds recovery if a device is lost.")]),e._v(" "),t("p",[e._v("Advanced versions of live online sync allow users to open the same wallet on multiple devices. Users often do this despite it being challenging to do with Lightning applications since two devices running simultaneously can result in losing funds.")]),e._v(" "),t("h1",{attrs:{id:"privacy-preserving-payment-routing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#privacy-preserving-payment-routing"}},[e._v("#")]),e._v(" Privacy-preserving Payment Routing")]),e._v(" "),t("p",[e._v("Another commonly discussed issue is payment routing through the Lightning Network. This isn't easy because the route finder has to have some history of liquidity on the Lightning Network.")]),e._v(" "),t("p",[e._v("The most common method is to rely on a server for route-finding, which sees users' payment history and therefore compromises privacy. This may also pose long-term regulatory concerns for apps relying on such servers.")]),e._v(" "),t("p",[e._v("Without a server, the client needs to download the full Lightning graph. This can be slow and performance-compromising. Worse, the Lightning graph alone doesn’t provide enough information to achieve reliable payment success, leading to the possibility that transactions may take a long time to complete, or not go through at all.")]),e._v(" "),t("p",[e._v("To achieve better payment success, the client must send lots of payments, which can be done via probing (fake payments). Probing trains data on the network graph from a client's perspective and builds up a history of liquidity on the network. While this offers a solution, probing must be done consistently, requiring the client to be online 24/7. This could instead be done by an LSP, which can offer the resulting data to clients. Additionally, information is not super portable across LSPs, so each LSP needs to do its own probing.")]),e._v(" "),t("h1",{attrs:{id:"privacy-preserving-block-fetching"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#privacy-preserving-block-fetching"}},[e._v("#")]),e._v(" Privacy-preserving Block Fetching")]),e._v(" "),t("p",[e._v("For users to see their transaction history and balance, bitcoin and Lightning wallets need to connect to and download the blockchain. Each block contains a lot of data, making downloading the full blockchain on mobile devices impractical due to bandwidth constraints.")]),e._v(" "),t("p",[e._v("The most common way to obtain blockchain data is to connect to a server using Electrum or Esplora. To do this and get the relevant information, the client has to provide their user’s list of addresses, exposing transaction histories and balances.")]),e._v(" "),t("p",[e._v("It’s difficult to fetch blockchain data without giving up privacy. One way around this is to use compact block filters, which download data from a full node and only download a select amount of blocks. While compact block filters offer better privacy than a server and are more efficient than downloading the entire blockchain, the method isn’t perfect. Compact block filters are slow to sync and still require substantial bandwidth on the user’s device, making it a less enticing tradeoff for many wallets.")]),e._v(" "),t("p",[e._v("A third option, called private information retrieval, is more future-looking. This method is efficient for clients but expensive on the server side.")]),e._v(" "),t("h1",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("There are many obstacles to making non-custodial Lightning work privately on mobile devices, but it is doable. It requires a mobile-focused LN implementation, SDK, and infrastructure operated by an LSP or the application vendor. None of that needs to compromise user privacy or self-sovereignty, even though, in many designs, it does.")])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/34.2922e225.js b/assets/js/35.98570dd8.js similarity index 99% rename from assets/js/34.2922e225.js rename to assets/js/35.98570dd8.js index 0a315a4dd..8b13e77d1 100644 --- a/assets/js/34.2922e225.js +++ b/assets/js/35.98570dd8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{394:function(t,e,n){"use strict";n.r(e);var s=n(7),a=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("p",[t._v("The "),e("a",{attrs:{href:"https://github.com/lightningdevkit/lightning-liquidity",target:"_blank",rel:"noopener noreferrer"}},[t._v("lightning-liquidity"),e("OutboundLink")],1),t._v(" crate is an easy-to-integrate rust library that wallet developers and LSP operators can use to implement the LSP specification. The initial alpha release supports the core functionality of JIT channels under the "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSPS2 specification"),e("OutboundLink")],1),t._v(", with plans to expand support to other key areas such as the "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS1",target:"_blank",rel:"noopener noreferrer"}},[t._v("Channel Request protocol (LSPS1)"),e("OutboundLink")],1),t._v(", "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/edf3d925ed67405963421e7228897a343ecd53ee/LSPS5/README.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Webhook Notifications (LSPS5)"),e("OutboundLink")],1),t._v(", and the next iteration of "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/db0e99e8b65641a18c2d9b9fdf22c2dbae2af32d/LSPS4/README.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("JIT Channels (LSPS4 - Continuous JIT Channels)"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[t._v("The lightning-liquidity release marks a significant milestone in ongoing efforts to make the Lightning Network more accessible and user-friendly.")]),t._v(" "),e("h2",{attrs:{id:"how-it-all-started-lightnings-liquidity-problem"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-it-all-started-lightnings-liquidity-problem"}},[t._v("#")]),t._v(" How It All Started: Lightning's Liquidity Problem")]),t._v(" "),e("p",[t._v("The Lightning Network offers some relief from bitcoin’s inherent transaction speed and cost limitations. Lightning relies on a network of payment channels facilitating nearly instant, low-fee transactions. However, the promise of this technology comes with its own "),e("a",{attrs:{href:"https://lightningdevkit.org/blog/the-challenges-of-developing-non-custodial-lightning-on-mobile",target:"_blank",rel:"noopener noreferrer"}},[t._v("set of challenges"),e("OutboundLink")],1),t._v(", particularly around obtaining inbound liquidity.")]),t._v(" "),e("p",[t._v("To receive a payment, a user must have a payment channel with sufficient funds on the counterparty's side. This upfront liquidity requirement demands coordination with a counterparty willing to sell said liquidity, which has historically posed a significant barrier to entry for new users.")]),t._v(" "),e("h2",{attrs:{id:"current-approaches-and-their-shortcomings"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#current-approaches-and-their-shortcomings"}},[t._v("#")]),t._v(" Current Approaches and Their Shortcomings")]),t._v(" "),e("p",[t._v("Wallet developers often implement their own Lightning Service Provider (LSP) to distribute inbound liquidity to their users. LSPs work by agreeing to lock up their funds in channels for a fee. While this model enables more users to more easily participate in the network, it also has several problems:")]),t._v(" "),e("ul",[e("li",[e("p",[e("strong",[t._v("Lack of Interoperability")]),t._v(": Each wallet developer has to build their own LSP protocols and infrastructure, leading to a fragmented ecosystem where users are tied to specific wallets or services.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Reliability")]),t._v(": A single LSP means a single point of failure. An LSP with poorly managed liquidity could render users unable to send and receive payments.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Privacy")]),t._v(": Centralizing payments raises the potential for surveillance and data collection.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Censorship")]),t._v(": LSPs can block or be forced to block payments at their discretion.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Cost")]),t._v(": With limited competition, users could face high, non-market fees for obtaining liquidity.")])])]),t._v(" "),e("h2",{attrs:{id:"a-unified-solution-the-standardization-effort"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#a-unified-solution-the-standardization-effort"}},[t._v("#")]),t._v(" A Unified Solution: The Standardization Effort")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("A consortium of Lightning developers"),e("OutboundLink")],1),t._v(" recognized these challenges and came together with a mission to standardize a protocol for acquiring inbound liquidity. This effort aimed to create a blueprint that any wallet or LSP could adopt, fostering interoperability and competition.")]),t._v(" "),e("p",[t._v("The benefits of this standardization are:")]),t._v(" "),e("ul",[e("li",[e("p",[e("strong",[t._v("Efficiency")]),t._v(": A single, well-defined protocol simplifies the development process, enabling wallet and LSP creators to focus on innovation rather than reinventing the wheel.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Choice and Flexibility")]),t._v(": Users gain the freedom to switch between LSPs seamlessly, promoting a competitive market that drives up service quality and drives down costs.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Addressing Core Issues")]),t._v(": Diversifying the ecosystem tackles the fundamental concerns of reliability, privacy, censorship, and monopolistic practices.")])])]),t._v(" "),e("h2",{attrs:{id:"just-in-time-channels-a-cornerstone-of-the-new-protocol"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#just-in-time-channels-a-cornerstone-of-the-new-protocol"}},[t._v("#")]),t._v(" Just-In-Time Channels: A Cornerstone of the New Protocol")]),t._v(" "),e("p",[t._v("Just-In-Time (JIT) channels are the heart of the standardized protocol. These channels lower the barrier to entry for new users by allowing anyone to receive bitcoin payments over the Lightning Network without bitcoin or liquidity management.")]),t._v(" "),e("p",[t._v("Here's how it works: a user requests a Lightning invoice for an incoming payment. Upon payment, the LSP intercepts this payment, opens a 0-conf channel to the user, deducts their fee and forwards the rest of the payment to the user. This process happens almost instantaneously, removing the need for users to understand or manage liquidity themselves.")]),t._v(" "),e("h2",{attrs:{id:"introducing-lightning-liquidity"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introducing-lightning-liquidity"}},[t._v("#")]),t._v(" Introducing "),e("code",[t._v("lightning-liquidity")])]),t._v(" "),e("p",[e("code",[t._v("lightning-liquidity")]),t._v(" provides a comprehensive toolkit for implementing the JIT channel protocol and other aspects of the LSP specification. This open standard streamlines the development process and ensures that a broader audience can access the benefits of the Lightning Network.")]),t._v(" "),e("h2",{attrs:{id:"how-it-works-for-developers-and-businesses"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-it-works-for-developers-and-businesses"}},[t._v("#")]),t._v(" How It Works: For Developers and Businesses")]),t._v(" "),e("p",[t._v('For wallet developers, integrating "lightning-liquidity" offers users immediate access to the Lightning Network\'s capabilities without the traditional hurdles of securing inbound liquidity. Developers can embed the library into their applications, making receiving payments seamless and efficient.')]),t._v(" "),e("p",[t._v("The “lightning-liquidity” crate is already integrated directly into the "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("ldk-node"),e("OutboundLink")],1),t._v(" project allowing for an extremely easy way to get started. Here’s a short example of how to get inbound liquidity using the new liquidity functionality of ldk-node:")]),t._v(" "),e("div",{staticClass:"language-rust extra-class"},[e("pre",{pre:!0,attrs:{class:"language-rust"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning_invoice"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("msgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_node_id "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LSP_NODE_ID"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_node_addr "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LSP_IP_ADDR:LSP_PORT"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_token "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("“"),e("span",{pre:!0,attrs:{class:"token constant"}},[t._v("LSP_TOKEN")]),t._v("”"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// tell ldk-node we want to source liquidity using LSPS2")]),t._v("\n\tbuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_liquidity_source_lsps2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lsp_node_addr"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lsp_node_id"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lsp_token"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" builder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// how much I want to receive")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice_amount_msat "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500_000_000")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the maximum I’m willing to pay in fees for the channel from the LSP")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" max_total_fee_limit_msat "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5_000_000")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the invoice I receive will be valid for this many seconds")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice_expiry_seconds "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3600")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get an invoice I can have paid without needing to set up any channels")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("receive_payment_via_jit_channel")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice_amount_msat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" “invoice description”"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" invoice_expiry_seconds"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("max_total_fee_limit_msat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),e("p",[t._v("If you are not using ldk-node then here is some example code that will help you get started implementing “lightning-liquidity” into your LDK based wallet: https://gist.github.com/johncantrell97/1d869aedcb8aef3f69874c15a0793dae")]),t._v(" "),e("p",[t._v('Businesses looking to operate as LSPs can easily leverage "lightning-liquidity" to offer liquidity services. The library simplifies the technical complexities involved in channel management, allowing businesses to focus on providing value to their customers rather than dealing with the intricacies of the Lightning Network protocol.')]),t._v(" "),e("p",[t._v("The LSPS2 protocol enables LSPs to earn a fee from every channel sold to wallet users. This fee consists of a minimum fee and a proportional fee. The proportional fee allows LSPs to earn a fee proportional to the payment size they need to route over the new channel. In contrast, the minimum fee ensures the fees they earn are guaranteed to be enough to cover their costs regardless of the payment size.")]),t._v(" "),e("p",[t._v("The protocol also allows LSPs to require and offer unique tokens that users or wallet developers can supply when requesting liquidity. The LSP can then dynamically adjust fees and channel parameters based on these tokens, allowing them to broker unique deals that cater to a wide range of potential requirements.")]),t._v(" "),e("p",[t._v("LDK LSP Server Example: https://gist.github.com/johncantrell97/dc682d2d75a0331fa83cb10a54f62b74")]),t._v(" "),e("h2",{attrs:{id:"join-us-in-shaping-the-future"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#join-us-in-shaping-the-future"}},[t._v("#")]),t._v(" Join Us in Shaping the Future")]),t._v(" "),e("p",[t._v('The launch of "lightning-liquidity" is just the beginning. We are committed to continuous improvement and expansion of the library to meet the evolving needs of the Lightning Network community. We encourage feedback, contributions, and collaboration from developers, businesses, and users. Together, we can unlock the full potential of the Lightning Network, making instant, low-cost Bitcoin transactions a reality for users worldwide.')]),t._v(" "),e("p",[t._v("For more information on the "),e("code",[t._v("lightning-liquidity")]),t._v(" library, the LSP specification, and how you can contribute to this transformative project, visit "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("the specification repository"),e("OutboundLink")],1),t._v(" and "),e("a",{attrs:{href:"https://github.com/lightningdevkit/lightning-liquidity",target:"_blank",rel:"noopener noreferrer"}},[t._v("lightning-liquidity GitHub repository"),e("OutboundLink")],1),t._v(". Together, we can build a more robust, efficient, and open Lightning Network.")])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{399:function(t,e,n){"use strict";n.r(e);var s=n(7),a=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("p",[t._v("The "),e("a",{attrs:{href:"https://github.com/lightningdevkit/lightning-liquidity",target:"_blank",rel:"noopener noreferrer"}},[t._v("lightning-liquidity"),e("OutboundLink")],1),t._v(" crate is an easy-to-integrate rust library that wallet developers and LSP operators can use to implement the LSP specification. The initial alpha release supports the core functionality of JIT channels under the "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2",target:"_blank",rel:"noopener noreferrer"}},[t._v("LSPS2 specification"),e("OutboundLink")],1),t._v(", with plans to expand support to other key areas such as the "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS1",target:"_blank",rel:"noopener noreferrer"}},[t._v("Channel Request protocol (LSPS1)"),e("OutboundLink")],1),t._v(", "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/edf3d925ed67405963421e7228897a343ecd53ee/LSPS5/README.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Webhook Notifications (LSPS5)"),e("OutboundLink")],1),t._v(", and the next iteration of "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp/blob/db0e99e8b65641a18c2d9b9fdf22c2dbae2af32d/LSPS4/README.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("JIT Channels (LSPS4 - Continuous JIT Channels)"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[t._v("The lightning-liquidity release marks a significant milestone in ongoing efforts to make the Lightning Network more accessible and user-friendly.")]),t._v(" "),e("h2",{attrs:{id:"how-it-all-started-lightnings-liquidity-problem"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-it-all-started-lightnings-liquidity-problem"}},[t._v("#")]),t._v(" How It All Started: Lightning's Liquidity Problem")]),t._v(" "),e("p",[t._v("The Lightning Network offers some relief from bitcoin’s inherent transaction speed and cost limitations. Lightning relies on a network of payment channels facilitating nearly instant, low-fee transactions. However, the promise of this technology comes with its own "),e("a",{attrs:{href:"https://lightningdevkit.org/blog/the-challenges-of-developing-non-custodial-lightning-on-mobile",target:"_blank",rel:"noopener noreferrer"}},[t._v("set of challenges"),e("OutboundLink")],1),t._v(", particularly around obtaining inbound liquidity.")]),t._v(" "),e("p",[t._v("To receive a payment, a user must have a payment channel with sufficient funds on the counterparty's side. This upfront liquidity requirement demands coordination with a counterparty willing to sell said liquidity, which has historically posed a significant barrier to entry for new users.")]),t._v(" "),e("h2",{attrs:{id:"current-approaches-and-their-shortcomings"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#current-approaches-and-their-shortcomings"}},[t._v("#")]),t._v(" Current Approaches and Their Shortcomings")]),t._v(" "),e("p",[t._v("Wallet developers often implement their own Lightning Service Provider (LSP) to distribute inbound liquidity to their users. LSPs work by agreeing to lock up their funds in channels for a fee. While this model enables more users to more easily participate in the network, it also has several problems:")]),t._v(" "),e("ul",[e("li",[e("p",[e("strong",[t._v("Lack of Interoperability")]),t._v(": Each wallet developer has to build their own LSP protocols and infrastructure, leading to a fragmented ecosystem where users are tied to specific wallets or services.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Reliability")]),t._v(": A single LSP means a single point of failure. An LSP with poorly managed liquidity could render users unable to send and receive payments.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Privacy")]),t._v(": Centralizing payments raises the potential for surveillance and data collection.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Censorship")]),t._v(": LSPs can block or be forced to block payments at their discretion.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Cost")]),t._v(": With limited competition, users could face high, non-market fees for obtaining liquidity.")])])]),t._v(" "),e("h2",{attrs:{id:"a-unified-solution-the-standardization-effort"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#a-unified-solution-the-standardization-effort"}},[t._v("#")]),t._v(" A Unified Solution: The Standardization Effort")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("A consortium of Lightning developers"),e("OutboundLink")],1),t._v(" recognized these challenges and came together with a mission to standardize a protocol for acquiring inbound liquidity. This effort aimed to create a blueprint that any wallet or LSP could adopt, fostering interoperability and competition.")]),t._v(" "),e("p",[t._v("The benefits of this standardization are:")]),t._v(" "),e("ul",[e("li",[e("p",[e("strong",[t._v("Efficiency")]),t._v(": A single, well-defined protocol simplifies the development process, enabling wallet and LSP creators to focus on innovation rather than reinventing the wheel.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Choice and Flexibility")]),t._v(": Users gain the freedom to switch between LSPs seamlessly, promoting a competitive market that drives up service quality and drives down costs.")])]),t._v(" "),e("li",[e("p",[e("strong",[t._v("Addressing Core Issues")]),t._v(": Diversifying the ecosystem tackles the fundamental concerns of reliability, privacy, censorship, and monopolistic practices.")])])]),t._v(" "),e("h2",{attrs:{id:"just-in-time-channels-a-cornerstone-of-the-new-protocol"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#just-in-time-channels-a-cornerstone-of-the-new-protocol"}},[t._v("#")]),t._v(" Just-In-Time Channels: A Cornerstone of the New Protocol")]),t._v(" "),e("p",[t._v("Just-In-Time (JIT) channels are the heart of the standardized protocol. These channels lower the barrier to entry for new users by allowing anyone to receive bitcoin payments over the Lightning Network without bitcoin or liquidity management.")]),t._v(" "),e("p",[t._v("Here's how it works: a user requests a Lightning invoice for an incoming payment. Upon payment, the LSP intercepts this payment, opens a 0-conf channel to the user, deducts their fee and forwards the rest of the payment to the user. This process happens almost instantaneously, removing the need for users to understand or manage liquidity themselves.")]),t._v(" "),e("h2",{attrs:{id:"introducing-lightning-liquidity"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introducing-lightning-liquidity"}},[t._v("#")]),t._v(" Introducing "),e("code",[t._v("lightning-liquidity")])]),t._v(" "),e("p",[e("code",[t._v("lightning-liquidity")]),t._v(" provides a comprehensive toolkit for implementing the JIT channel protocol and other aspects of the LSP specification. This open standard streamlines the development process and ensures that a broader audience can access the benefits of the Lightning Network.")]),t._v(" "),e("h2",{attrs:{id:"how-it-works-for-developers-and-businesses"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#how-it-works-for-developers-and-businesses"}},[t._v("#")]),t._v(" How It Works: For Developers and Businesses")]),t._v(" "),e("p",[t._v('For wallet developers, integrating "lightning-liquidity" offers users immediate access to the Lightning Network\'s capabilities without the traditional hurdles of securing inbound liquidity. Developers can embed the library into their applications, making receiving payments seamless and efficient.')]),t._v(" "),e("p",[t._v("The “lightning-liquidity” crate is already integrated directly into the "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[t._v("ldk-node"),e("OutboundLink")],1),t._v(" project allowing for an extremely easy way to get started. Here’s a short example of how to get inbound liquidity using the new liquidity functionality of ldk-node:")]),t._v(" "),e("div",{staticClass:"language-rust extra-class"},[e("pre",{pre:!0,attrs:{class:"language-rust"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning_invoice"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("lightning"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("msgs"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ldk_node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_node_id "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LSP_NODE_ID"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_node_addr "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LSP_IP_ADDR:LSP_PORT"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lsp_token "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("“"),e("span",{pre:!0,attrs:{class:"token constant"}},[t._v("LSP_TOKEN")]),t._v("”"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Builder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// tell ldk-node we want to source liquidity using LSPS2")]),t._v("\n\tbuilder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_liquidity_source_lsps2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lsp_node_addr"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lsp_node_id"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" lsp_token"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" node "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" builder"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tnode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// how much I want to receive")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice_amount_msat "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("500_000_000")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the maximum I’m willing to pay in fees for the channel from the LSP")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" max_total_fee_limit_msat "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5_000_000")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the invoice I receive will be valid for this many seconds")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice_expiry_seconds "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3600")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get an invoice I can have paid without needing to set up any channels")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" node"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("receive_payment_via_jit_channel")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice_amount_msat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" “invoice description”"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" invoice_expiry_seconds"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("max_total_fee_limit_msat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),e("p",[t._v("If you are not using ldk-node then here is some example code that will help you get started implementing “lightning-liquidity” into your LDK based wallet: https://gist.github.com/johncantrell97/1d869aedcb8aef3f69874c15a0793dae")]),t._v(" "),e("p",[t._v('Businesses looking to operate as LSPs can easily leverage "lightning-liquidity" to offer liquidity services. The library simplifies the technical complexities involved in channel management, allowing businesses to focus on providing value to their customers rather than dealing with the intricacies of the Lightning Network protocol.')]),t._v(" "),e("p",[t._v("The LSPS2 protocol enables LSPs to earn a fee from every channel sold to wallet users. This fee consists of a minimum fee and a proportional fee. The proportional fee allows LSPs to earn a fee proportional to the payment size they need to route over the new channel. In contrast, the minimum fee ensures the fees they earn are guaranteed to be enough to cover their costs regardless of the payment size.")]),t._v(" "),e("p",[t._v("The protocol also allows LSPs to require and offer unique tokens that users or wallet developers can supply when requesting liquidity. The LSP can then dynamically adjust fees and channel parameters based on these tokens, allowing them to broker unique deals that cater to a wide range of potential requirements.")]),t._v(" "),e("p",[t._v("LDK LSP Server Example: https://gist.github.com/johncantrell97/dc682d2d75a0331fa83cb10a54f62b74")]),t._v(" "),e("h2",{attrs:{id:"join-us-in-shaping-the-future"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#join-us-in-shaping-the-future"}},[t._v("#")]),t._v(" Join Us in Shaping the Future")]),t._v(" "),e("p",[t._v('The launch of "lightning-liquidity" is just the beginning. We are committed to continuous improvement and expansion of the library to meet the evolving needs of the Lightning Network community. We encourage feedback, contributions, and collaboration from developers, businesses, and users. Together, we can unlock the full potential of the Lightning Network, making instant, low-cost Bitcoin transactions a reality for users worldwide.')]),t._v(" "),e("p",[t._v("For more information on the "),e("code",[t._v("lightning-liquidity")]),t._v(" library, the LSP specification, and how you can contribute to this transformative project, visit "),e("a",{attrs:{href:"https://github.com/BitcoinAndLightningLayerSpecs/lsp",target:"_blank",rel:"noopener noreferrer"}},[t._v("the specification repository"),e("OutboundLink")],1),t._v(" and "),e("a",{attrs:{href:"https://github.com/lightningdevkit/lightning-liquidity",target:"_blank",rel:"noopener noreferrer"}},[t._v("lightning-liquidity GitHub repository"),e("OutboundLink")],1),t._v(". Together, we can build a more robust, efficient, and open Lightning Network.")])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/35.e7e2fd06.js b/assets/js/36.504d0af4.js similarity index 98% rename from assets/js/35.e7e2fd06.js rename to assets/js/36.504d0af4.js index 754e2850d..40b3dcf39 100644 --- a/assets/js/35.e7e2fd06.js +++ b/assets/js/36.504d0af4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{395:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Support for 0-conf channels became available in the Lightning Development Kit’s June 2022, "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/releases/tag/v0.0.107",target:"_blank",rel:"noopener noreferrer"}},[e._v("107 release"),t("OutboundLink")],1),e._v(". A 0-conf channel allows peers to start using a channel as soon as the funding transaction is broadcast instead of waiting for multiple confirmations. By temporarily trusting the person initiating the channel open, 0-conf channels enable instant onboarding to the Lightning Network.")]),e._v(" "),t("h2",{attrs:{id:"what-is-a-confirmation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-is-a-confirmation"}},[e._v("#")]),e._v(" What is a confirmation?")]),e._v(" "),t("p",[e._v("A confirmation refers to each block that has been mined with a particular transaction included in the chain. When a transaction is first broadcast to the network but has not yet been included in a block, it has zero confirmations. When the transaction is included in a block, it is said to have one confirmation. Each block mined on top of the first block gives a transaction additional confirmations.")]),e._v(" "),t("h2",{attrs:{id:"why-does-the-number-of-confirmations-matter"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-does-the-number-of-confirmations-matter"}},[e._v("#")]),e._v(" Why does the number of confirmations matter?")]),e._v(" "),t("p",[e._v("It’s a way to measure the security and finality of transactions. The only way a miner can reverse a transaction is by a process called reorganization. This requires the miner to build a chain of blocks with more work than the currently accepted chain. Each block mined on top of a block that contains a transaction makes it harder to reorganize. In bitcoin’s history, we’ve seen a 4-block reorganization only a couple of times, a 3-block reorganization a handful of times, a 2-block reorganization a few dozen times, and hundreds of 1-block reorganizations.")]),e._v(" "),t("p",[e._v("This is why you should wait six confirmations before considering a high-value transaction complete. A 0-conf transaction is dangerous to accept if you don’t trust the sender since there’s no guarantee that it will ever be included in a block. It’s possible that the fee is too low or another transaction double spends its inputs.")]),e._v(" "),t("h2",{attrs:{id:"what-does-this-have-to-do-with-the-lightning-network"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-does-this-have-to-do-with-the-lightning-network"}},[e._v("#")]),e._v(" What does this have to do with the Lightning Network?")]),e._v(" "),t("p",[e._v("When you open a channel on the Lightning Network, you create and broadcast a transaction that funds a multi-sig address shared between channel partners. Most implementations wait for six confirmations before letting a channel route payments. Like any transaction, it could be double-spent, have erroneously low fees, or be reorganized out by miners. If you receive money over a channel where the funding transaction is never confirmed, you will lose any money received or forwarded over that channel.")]),e._v(" "),t("p",[e._v("That brings us to 0-conf channels, which can be used once the transaction appears in both parties' mempools without being mined. This means that the same risks exist when accepting payments over a 0-conf channel as on-chain payments with zero confirmations. However, If you accept a 0-conf payment or channel then you are putting trust into the system.")]),e._v(" "),t("p",[e._v("0-conf channels are somewhat controversial because one of bitcoin’s main benefits is that it enables peer-to-peer payments without requiring you to trust your peers or any other intermediaries. With 0-conf channels, you trust that your peer won’t attempt to double-spend the transaction inputs and that miners will include and build on top of this transaction. While you can do some things to gain confidence that the transaction will confirm, such as verifying the fee rate and being well connected to the network, you can never be certain.")]),e._v(" "),t("p",[e._v("Despite the trust required when working with 0-conf transactions, it’s worth noting that in the case of 0-conf channels, the trust is only with your peer, which is not necessarily the person sending you the money. This is quite different from 0-conf on-chain payments where you have to trust every individual sender.")]),e._v(" "),t("h2",{attrs:{id:"why-or-when-might-0-conf-channels-be-useful"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-or-when-might-0-conf-channels-be-useful"}},[e._v("#")]),e._v(" Why or when might 0-conf channels be useful?")]),e._v(" "),t("p",[e._v("Well, they enable instant Lightning payments where trust is minimized as confirmations occur. This can be useful in situations where you already trust your peers to some extent, such as friends, family, or reliable business relationships.")]),e._v(" "),t("p",[e._v("0-conf channels can also enable some interesting liquidity/onboarding use-cases. If you trust your LSP or wallet provider, it’s possible to receive a payment over Lightning without having to set up a channel first. Your LSP or wallet provider can open a 0-conf channel with you on-demand as your first payment arrives.")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("0-conf channels can be a useful tool in situations where there is some trust. Do not accept 0-conf channels by default or from people you don’t know. Check out "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=JjuN6aVv9DI",target:"_blank",rel:"noopener noreferrer"}},[e._v("this video"),t("OutboundLink")],1),e._v(" to see how support for 0-conf channels was added to Sensei, an LDK-based Lightning node.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{400:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("Support for 0-conf channels became available in the Lightning Development Kit’s June 2022, "),t("a",{attrs:{href:"https://github.com/lightningdevkit/rust-lightning/releases/tag/v0.0.107",target:"_blank",rel:"noopener noreferrer"}},[e._v("107 release"),t("OutboundLink")],1),e._v(". A 0-conf channel allows peers to start using a channel as soon as the funding transaction is broadcast instead of waiting for multiple confirmations. By temporarily trusting the person initiating the channel open, 0-conf channels enable instant onboarding to the Lightning Network.")]),e._v(" "),t("h2",{attrs:{id:"what-is-a-confirmation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-is-a-confirmation"}},[e._v("#")]),e._v(" What is a confirmation?")]),e._v(" "),t("p",[e._v("A confirmation refers to each block that has been mined with a particular transaction included in the chain. When a transaction is first broadcast to the network but has not yet been included in a block, it has zero confirmations. When the transaction is included in a block, it is said to have one confirmation. Each block mined on top of the first block gives a transaction additional confirmations.")]),e._v(" "),t("h2",{attrs:{id:"why-does-the-number-of-confirmations-matter"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-does-the-number-of-confirmations-matter"}},[e._v("#")]),e._v(" Why does the number of confirmations matter?")]),e._v(" "),t("p",[e._v("It’s a way to measure the security and finality of transactions. The only way a miner can reverse a transaction is by a process called reorganization. This requires the miner to build a chain of blocks with more work than the currently accepted chain. Each block mined on top of a block that contains a transaction makes it harder to reorganize. In bitcoin’s history, we’ve seen a 4-block reorganization only a couple of times, a 3-block reorganization a handful of times, a 2-block reorganization a few dozen times, and hundreds of 1-block reorganizations.")]),e._v(" "),t("p",[e._v("This is why you should wait six confirmations before considering a high-value transaction complete. A 0-conf transaction is dangerous to accept if you don’t trust the sender since there’s no guarantee that it will ever be included in a block. It’s possible that the fee is too low or another transaction double spends its inputs.")]),e._v(" "),t("h2",{attrs:{id:"what-does-this-have-to-do-with-the-lightning-network"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-does-this-have-to-do-with-the-lightning-network"}},[e._v("#")]),e._v(" What does this have to do with the Lightning Network?")]),e._v(" "),t("p",[e._v("When you open a channel on the Lightning Network, you create and broadcast a transaction that funds a multi-sig address shared between channel partners. Most implementations wait for six confirmations before letting a channel route payments. Like any transaction, it could be double-spent, have erroneously low fees, or be reorganized out by miners. If you receive money over a channel where the funding transaction is never confirmed, you will lose any money received or forwarded over that channel.")]),e._v(" "),t("p",[e._v("That brings us to 0-conf channels, which can be used once the transaction appears in both parties' mempools without being mined. This means that the same risks exist when accepting payments over a 0-conf channel as on-chain payments with zero confirmations. However, If you accept a 0-conf payment or channel then you are putting trust into the system.")]),e._v(" "),t("p",[e._v("0-conf channels are somewhat controversial because one of bitcoin’s main benefits is that it enables peer-to-peer payments without requiring you to trust your peers or any other intermediaries. With 0-conf channels, you trust that your peer won’t attempt to double-spend the transaction inputs and that miners will include and build on top of this transaction. While you can do some things to gain confidence that the transaction will confirm, such as verifying the fee rate and being well connected to the network, you can never be certain.")]),e._v(" "),t("p",[e._v("Despite the trust required when working with 0-conf transactions, it’s worth noting that in the case of 0-conf channels, the trust is only with your peer, which is not necessarily the person sending you the money. This is quite different from 0-conf on-chain payments where you have to trust every individual sender.")]),e._v(" "),t("h2",{attrs:{id:"why-or-when-might-0-conf-channels-be-useful"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#why-or-when-might-0-conf-channels-be-useful"}},[e._v("#")]),e._v(" Why or when might 0-conf channels be useful?")]),e._v(" "),t("p",[e._v("Well, they enable instant Lightning payments where trust is minimized as confirmations occur. This can be useful in situations where you already trust your peers to some extent, such as friends, family, or reliable business relationships.")]),e._v(" "),t("p",[e._v("0-conf channels can also enable some interesting liquidity/onboarding use-cases. If you trust your LSP or wallet provider, it’s possible to receive a payment over Lightning without having to set up a channel first. Your LSP or wallet provider can open a 0-conf channel with you on-demand as your first payment arrives.")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("0-conf channels can be a useful tool in situations where there is some trust. Do not accept 0-conf channels by default or from people you don’t know. Check out "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=JjuN6aVv9DI",target:"_blank",rel:"noopener noreferrer"}},[e._v("this video"),t("OutboundLink")],1),e._v(" to see how support for 0-conf channels was added to Sensei, an LDK-based Lightning node.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/36.dd2de090.js b/assets/js/37.723e1c5b.js similarity index 99% rename from assets/js/36.dd2de090.js rename to assets/js/37.723e1c5b.js index 241545fca..c28c475a6 100644 --- a/assets/js/36.dd2de090.js +++ b/assets/js/37.723e1c5b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{396:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"block-source"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#block-source"}},[t._v("#")]),t._v(" Block Source")]),t._v(" "),s("p",[t._v("Implementing the "),s("code",[t._v("BlockSource")]),t._v(" interface requires defining methods for fetching\nheaders, blocks, and the best block hash.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockSource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_header")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHeaderData")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_best_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("For instance, you may implement this interface by querying Bitcoin Core's JSON\nRPC interface, which happens to be a sample implementation provided by\n"),s("code",[t._v("lightning-block-sync")]),t._v(".")]),t._v(" "),s("p",[t._v("Let's walk through the use case where LDK receives full blocks.")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{401:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"block-source"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#block-source"}},[t._v("#")]),t._v(" Block Source")]),t._v(" "),s("p",[t._v("Implementing the "),s("code",[t._v("BlockSource")]),t._v(" interface requires defining methods for fetching\nheaders, blocks, and the best block hash.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockSource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_header")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHeaderData")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_best_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("For instance, you may implement this interface by querying Bitcoin Core's JSON\nRPC interface, which happens to be a sample implementation provided by\n"),s("code",[t._v("lightning-block-sync")]),t._v(".")]),t._v(" "),s("p",[t._v("Let's walk through the use case where LDK receives full blocks.")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/37.d1a079e6.js b/assets/js/38.fe496d82.js similarity index 97% rename from assets/js/37.d1a079e6.js rename to assets/js/38.fe496d82.js index befcdecfd..51b7f583f 100644 --- a/assets/js/37.d1a079e6.js +++ b/assets/js/38.fe496d82.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{397:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"chain-activity"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#chain-activity"}},[e._v("#")]),e._v(" Chain Activity")]),e._v(" "),t("p",[e._v("Initially, our node doesn't have any channels and hence has no data to monitor\nfor on-chain. When a channel is opened with a peer, the "),t("code",[e._v("ChannelManager")]),e._v(" creates\na "),t("code",[e._v("ChannelMonitor")]),e._v(" and passes it to the "),t("code",[e._v("ChainMonitor")]),e._v(" to watch.")]),e._v(" "),t("p",[e._v("At this point, you need to feed LDK any chain data of interest so that it can\nrespond accordingly. It supports receiving either full blocks or pre-filtered\nblocks using the "),t("code",[e._v("chain::Listen")]),e._v(" interface. While block data can be sourced from\nanywhere, it is your responsibility to call the "),t("code",[e._v("block_connected")]),e._v(" and\n"),t("code",[e._v("block_disconnected")]),e._v(" methods on "),t("code",[e._v("ChannelManager")]),e._v(" and "),t("code",[e._v("ChainMonitor")]),e._v(". This allows\nthem to update channel state and respond to on-chain events, respectively.")]),e._v(" "),t("p",[e._v("LDK comes with a "),t("code",[e._v("lightning-block-sync")]),e._v(" utility that handles polling a block\nsource for the best chain tip, detecting chain forks, and notifying listeners\nwhen blocks are connected and disconnected. It can be configured to:")]),e._v(" "),t("ul",[t("li",[e._v("Poll a custom "),t("code",[e._v("BlockSource")])]),e._v(" "),t("li",[e._v("Notify "),t("code",[e._v("ChannelManager")]),e._v(" and "),t("code",[e._v("ChainMonitor")]),e._v(" of block events")])]),e._v(" "),t("p",[e._v("It is your choice as to whether you use this utility or your own to feed the\nrequired chain data to LDK. If you choose to use it, you will need to implement\nthe "),t("code",[e._v("BlockSource")]),e._v(" interface or use one of the samples that it provides.")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),t("p",[e._v("Currently, "),t("code",[e._v("lightning-block-sync")]),e._v(" is only available in Rust.")])])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{402:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"chain-activity"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#chain-activity"}},[e._v("#")]),e._v(" Chain Activity")]),e._v(" "),t("p",[e._v("Initially, our node doesn't have any channels and hence has no data to monitor\nfor on-chain. When a channel is opened with a peer, the "),t("code",[e._v("ChannelManager")]),e._v(" creates\na "),t("code",[e._v("ChannelMonitor")]),e._v(" and passes it to the "),t("code",[e._v("ChainMonitor")]),e._v(" to watch.")]),e._v(" "),t("p",[e._v("At this point, you need to feed LDK any chain data of interest so that it can\nrespond accordingly. It supports receiving either full blocks or pre-filtered\nblocks using the "),t("code",[e._v("chain::Listen")]),e._v(" interface. While block data can be sourced from\nanywhere, it is your responsibility to call the "),t("code",[e._v("block_connected")]),e._v(" and\n"),t("code",[e._v("block_disconnected")]),e._v(" methods on "),t("code",[e._v("ChannelManager")]),e._v(" and "),t("code",[e._v("ChainMonitor")]),e._v(". This allows\nthem to update channel state and respond to on-chain events, respectively.")]),e._v(" "),t("p",[e._v("LDK comes with a "),t("code",[e._v("lightning-block-sync")]),e._v(" utility that handles polling a block\nsource for the best chain tip, detecting chain forks, and notifying listeners\nwhen blocks are connected and disconnected. It can be configured to:")]),e._v(" "),t("ul",[t("li",[e._v("Poll a custom "),t("code",[e._v("BlockSource")])]),e._v(" "),t("li",[e._v("Notify "),t("code",[e._v("ChannelManager")]),e._v(" and "),t("code",[e._v("ChainMonitor")]),e._v(" of block events")])]),e._v(" "),t("p",[e._v("It is your choice as to whether you use this utility or your own to feed the\nrequired chain data to LDK. If you choose to use it, you will need to implement\nthe "),t("code",[e._v("BlockSource")]),e._v(" interface or use one of the samples that it provides.")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),t("p",[e._v("Currently, "),t("code",[e._v("lightning-block-sync")]),e._v(" is only available in Rust.")])])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/38.23a0ab92.js b/assets/js/39.8ae8d1bb.js similarity index 98% rename from assets/js/38.23a0ab92.js rename to assets/js/39.8ae8d1bb.js index 0c5c00aaf..b73bee541 100644 --- a/assets/js/38.23a0ab92.js +++ b/assets/js/39.8ae8d1bb.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{398:function(t,e,n){"use strict";n.r(e);var i=n(7),o=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"confirmed-transactions"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#confirmed-transactions"}},[t._v("#")]),t._v(" Confirmed Transactions")]),t._v(" "),e("p",[t._v("Up until this point, we've explored how to notify LDK of chain activity using\nblocks. But what if you're sourcing chain activity from a place that doesn't\nprovide a block-centric interface, like Electrum?")]),t._v(" "),e("p",[t._v("LDK's "),e("code",[t._v("ChannelManager")]),t._v(" and "),e("code",[t._v("ChainMonitor")]),t._v(" implement a\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Confirm.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Confirm")]),e("OutboundLink")],1),t._v("\ninterface to support this use case, analogous to the block-oriented\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Listen.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Listen")]),e("OutboundLink")],1),t._v("\ninterface which we've been using up until now. With this alternative approach,\nyou still need to give LDK information about chain activity,\nbut only for transactions of interest. To this end, you must call\n"),e("code",[t._v("Confirm::transactions_confirmed")]),t._v(" when any transactions identified by\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Filter")]),e("OutboundLink")],1),t._v("'s\n"),e("code",[t._v("register_tx")]),t._v("/"),e("code",[t._v("register_output")]),t._v(" methods are confirmed.")]),t._v(" "),e("p",[t._v("You also need to notify LDK of any transactions with insufficient confirmations\nthat have been reorganized out of the chain. Transactions that need to be monitored for such\nreorganization are returned by "),e("code",[t._v("Confirm::get_relevant_txids")]),t._v(". If any of these transactions become\nunconfirmed, you must call "),e("code",[t._v("Confirm::transaction_unconfirmed")]),t._v(".")]),t._v(" "),e("p",[t._v("Lastly, you must notify LDK whenever a new chain tip is available using\nthe "),e("code",[t._v("Confirm::best_block_updated")]),t._v(" method. See the documentation for a full\npicture of how this interface is intended to be used.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Note that the described methods of "),e("code",[t._v("Confirm")]),t._v(" must be called in accordance with the ordering requirements\ndescribed in the "),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Confirm.html#order",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("Confirm")]),t._v(" documentation"),e("OutboundLink")],1)])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Note that the described methods of "),e("code",[t._v("Confirm")]),t._v(" must be called both on the\n"),e("code",[t._v("ChannelManager")]),t._v(" "),e("em",[t._v("and")]),t._v(" the "),e("code",[t._v("ChainMonitor")]),t._v(".")])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Be advised that "),e("code",[t._v("chain::Confirm")]),t._v(" is a less mature interface than\n"),e("code",[t._v("chain::Listen")]),t._v(". As such, there is not yet a utility like\n"),e("code",[t._v("lightning-block-sync")]),t._v(" to use for interacting with clients like Electrum.")])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{403:function(t,e,n){"use strict";n.r(e);var i=n(7),o=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"confirmed-transactions"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#confirmed-transactions"}},[t._v("#")]),t._v(" Confirmed Transactions")]),t._v(" "),e("p",[t._v("Up until this point, we've explored how to notify LDK of chain activity using\nblocks. But what if you're sourcing chain activity from a place that doesn't\nprovide a block-centric interface, like Electrum?")]),t._v(" "),e("p",[t._v("LDK's "),e("code",[t._v("ChannelManager")]),t._v(" and "),e("code",[t._v("ChainMonitor")]),t._v(" implement a\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Confirm.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Confirm")]),e("OutboundLink")],1),t._v("\ninterface to support this use case, analogous to the block-oriented\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Listen.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Listen")]),e("OutboundLink")],1),t._v("\ninterface which we've been using up until now. With this alternative approach,\nyou still need to give LDK information about chain activity,\nbut only for transactions of interest. To this end, you must call\n"),e("code",[t._v("Confirm::transactions_confirmed")]),t._v(" when any transactions identified by\n"),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("chain::Filter")]),e("OutboundLink")],1),t._v("'s\n"),e("code",[t._v("register_tx")]),t._v("/"),e("code",[t._v("register_output")]),t._v(" methods are confirmed.")]),t._v(" "),e("p",[t._v("You also need to notify LDK of any transactions with insufficient confirmations\nthat have been reorganized out of the chain. Transactions that need to be monitored for such\nreorganization are returned by "),e("code",[t._v("Confirm::get_relevant_txids")]),t._v(". If any of these transactions become\nunconfirmed, you must call "),e("code",[t._v("Confirm::transaction_unconfirmed")]),t._v(".")]),t._v(" "),e("p",[t._v("Lastly, you must notify LDK whenever a new chain tip is available using\nthe "),e("code",[t._v("Confirm::best_block_updated")]),t._v(" method. See the documentation for a full\npicture of how this interface is intended to be used.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Note that the described methods of "),e("code",[t._v("Confirm")]),t._v(" must be called in accordance with the ordering requirements\ndescribed in the "),e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Confirm.html#order",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("Confirm")]),t._v(" documentation"),e("OutboundLink")],1)])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Note that the described methods of "),e("code",[t._v("Confirm")]),t._v(" must be called both on the\n"),e("code",[t._v("ChannelManager")]),t._v(" "),e("em",[t._v("and")]),t._v(" the "),e("code",[t._v("ChainMonitor")]),t._v(".")])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),e("p",[t._v("Be advised that "),e("code",[t._v("chain::Confirm")]),t._v(" is a less mature interface than\n"),e("code",[t._v("chain::Listen")]),t._v(". As such, there is not yet a utility like\n"),e("code",[t._v("lightning-block-sync")]),t._v(" to use for interacting with clients like Electrum.")])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/39.ad864211.js b/assets/js/40.19bc3e5e.js similarity index 94% rename from assets/js/39.ad864211.js rename to assets/js/40.19bc3e5e.js index be0aca498..0183dc1f2 100644 --- a/assets/js/39.ad864211.js +++ b/assets/js/40.19bc3e5e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{399:function(n,e,t){"use strict";t.r(e);var a=t(7),o=Object(a.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h1",{attrs:{id:"full-blocks"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#full-blocks"}},[n._v("#")]),n._v(" Full Blocks")]),n._v(" "),e("p",[n._v("If your Lightning node is backed by a Bitcoin full node, the operation is\nstraight forward: call the appropriate methods on "),e("code",[n._v("ChannelManager")]),n._v(" and\n"),e("code",[n._v("ChainMonitor")]),n._v(" as blocks are connected and disconnected. LDK will handle the\nrest!")]),n._v(" "),e("p",[n._v("So what happens? The "),e("code",[n._v("ChannelManager")]),n._v(" examines the block's transactions and\nupdates the internal channel state as needed. The "),e("code",[n._v("ChainMonitor")]),n._v(" will detect\nany spends of the channel funding transaction or any pertinent transaction\noutputs, tracking them as necessary.")]),n._v(" "),e("p",[n._v("If necessary, LDK will broadcast a transaction on your behalf. More on that\nlater. For now, let's look at the more interesting case of pre-filtered blocks.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{404:function(n,e,t){"use strict";t.r(e);var a=t(7),o=Object(a.a)({},(function(){var n=this,e=n._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":n.$parent.slotKey}},[e("h1",{attrs:{id:"full-blocks"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#full-blocks"}},[n._v("#")]),n._v(" Full Blocks")]),n._v(" "),e("p",[n._v("If your Lightning node is backed by a Bitcoin full node, the operation is\nstraight forward: call the appropriate methods on "),e("code",[n._v("ChannelManager")]),n._v(" and\n"),e("code",[n._v("ChainMonitor")]),n._v(" as blocks are connected and disconnected. LDK will handle the\nrest!")]),n._v(" "),e("p",[n._v("So what happens? The "),e("code",[n._v("ChannelManager")]),n._v(" examines the block's transactions and\nupdates the internal channel state as needed. The "),e("code",[n._v("ChainMonitor")]),n._v(" will detect\nany spends of the channel funding transaction or any pertinent transaction\noutputs, tracking them as necessary.")]),n._v(" "),e("p",[n._v("If necessary, LDK will broadcast a transaction on your behalf. More on that\nlater. For now, let's look at the more interesting case of pre-filtered blocks.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/40.d64c575a.js b/assets/js/41.f61ce3df.js similarity index 99% rename from assets/js/40.d64c575a.js rename to assets/js/41.f61ce3df.js index c779f31a4..db633a446 100644 --- a/assets/js/40.d64c575a.js +++ b/assets/js/41.f61ce3df.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{402:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"pre-filtered-blocks"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#pre-filtered-blocks"}},[t._v("#")]),t._v(" Pre-filtered Blocks")]),t._v(" "),s("p",[t._v("For environments that are resource constrained, receiving and processing all\ntransaction data may not be feasible. LDK handles this case by signaling back\nwhich transactions and outputs it is interested in. This information can then be\nused to filter blocks prior to sending them to your node.")]),t._v(" "),s("p",[t._v("For example, if your block source is an Electrum client, you can pass along this\ninformation to it. Or, if you are making use of a BIP 157 client, you can check\nif a block contains relevant transactions before fetching it.")]),t._v(" "),s("p",[t._v("So how does this work in practice? "),s("code",[t._v("ChainMonitor")]),t._v(" is parameterized by an\noptional type that implements "),s("code",[t._v("chain::Filter")]),t._v(":")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",java:"Java"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Txid")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"java",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" tx_filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FilterInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("When this is provided, "),s("code",[t._v("ChainMonitor")]),t._v(" will call back to the filter as channels\nare opened and blocks connected. This gives the opportunity for the source to\npre-filter blocks as desired.")]),t._v(" "),s("p",[t._v("Regardless, when a block is connected, its header must be processed by LDK.")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{406:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"pre-filtered-blocks"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#pre-filtered-blocks"}},[t._v("#")]),t._v(" Pre-filtered Blocks")]),t._v(" "),s("p",[t._v("For environments that are resource constrained, receiving and processing all\ntransaction data may not be feasible. LDK handles this case by signaling back\nwhich transactions and outputs it is interested in. This information can then be\nused to filter blocks prior to sending them to your node.")]),t._v(" "),s("p",[t._v("For example, if your block source is an Electrum client, you can pass along this\ninformation to it. Or, if you are making use of a BIP 157 client, you can check\nif a block contains relevant transactions before fetching it.")]),t._v(" "),s("p",[t._v("So how does this work in practice? "),s("code",[t._v("ChainMonitor")]),t._v(" is parameterized by an\noptional type that implements "),s("code",[t._v("chain::Filter")]),t._v(":")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",java:"Java"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Txid")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"java",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" tx_filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FilterInterface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token annotation punctuation"}},[t._v("@Override")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("public")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("When this is provided, "),s("code",[t._v("ChainMonitor")]),t._v(" will call back to the filter as channels\nare opened and blocks connected. This gives the opportunity for the source to\npre-filter blocks as desired.")]),t._v(" "),s("p",[t._v("Regardless, when a block is connected, its header must be processed by LDK.")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/41.40f10534.js b/assets/js/42.424ba564.js similarity index 93% rename from assets/js/41.40f10534.js rename to assets/js/42.424ba564.js index 02af537c4..c79234c59 100644 --- a/assets/js/41.40f10534.js +++ b/assets/js/42.424ba564.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{401:function(t,n,o){"use strict";o.r(n);var a=o(7),e=Object(a.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"transaction-broadcasting"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#transaction-broadcasting"}},[t._v("#")]),t._v(" Transaction Broadcasting")]),t._v(" "),n("p",[t._v("Inevitably, LDK will need to broadcast transactions on your behalf. As you\nnotify it of blocks, it will determine if it should broadcast a transaction and\ndo so using an implementation of "),n("code",[t._v("BroadcasterInterface")]),t._v(" that you have provided.")]),t._v(" "),n("p",[t._v("And as those transactions or those from your peers are confirmed on-chain, they\nwill be likewise processed when notified of a connected block. Thus, continuing\nthe cycle.")])])}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{407:function(t,n,o){"use strict";o.r(n);var a=o(7),e=Object(a.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"transaction-broadcasting"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#transaction-broadcasting"}},[t._v("#")]),t._v(" Transaction Broadcasting")]),t._v(" "),n("p",[t._v("Inevitably, LDK will need to broadcast transactions on your behalf. As you\nnotify it of blocks, it will determine if it should broadcast a transaction and\ndo so using an implementation of "),n("code",[t._v("BroadcasterInterface")]),t._v(" that you have provided.")]),t._v(" "),n("p",[t._v("And as those transactions or those from your peers are confirmed on-chain, they\nwill be likewise processed when notified of a connected block. Thus, continuing\nthe cycle.")])])}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/42.7c9c1955.js b/assets/js/43.783c39b3.js similarity index 99% rename from assets/js/42.7c9c1955.js rename to assets/js/43.783c39b3.js index 6aec6f579..c4a525520 100644 --- a/assets/js/42.7c9c1955.js +++ b/assets/js/43.783c39b3.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{403:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"closing-a-channel"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#closing-a-channel"}},[t._v("#")]),t._v(" Closing a Channel")]),t._v(" "),s("p",[t._v("Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs will be accepted on the given channel, and after additional timeout/the closing of all pending HTLCs, the channel will be closed on chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_channels")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("channel"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" channel"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("user_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" user_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Channel not found"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example: Cooperative close")]),t._v("\nchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to close channel"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example: Unilateral close")]),t._v("\nchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("force_close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to close channel"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Result_NoneAPIErrorZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_NoneAPIErrorZ_Err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle error")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful close")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add Channel Id in bytes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add Counterparty Node Id in bytes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("closeChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Channel Closed")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("To claim Funds directly into a custom wallet like BDK wallet using a custom "),s("code",[t._v("KeysManager")]),t._v(" see the "),s("RouterLink",{attrs:{to:"/key_management/"}},[t._v("Key Management")]),t._v(" guide for more info.")],1),t._v(" "),s("h1",{attrs:{id:"spendableoutputs-event-handling"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#spendableoutputs-event-handling"}},[t._v("#")]),t._v(" SpendableOutputs Event Handling")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SpendableOutputDescriptors, of which outputs is a vec of, are critical to keep track")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// of! While a `StaticOutput` descriptor is just an output to a static, well-known key,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// other descriptors are not currently ever regenerated for you by LDK. Once we return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// from this method, the descriptor will be gone, and you may lose track of some funds.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we simply persist them to disk, with a background task running which will try")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// to spend them regularly (possibly duplicatively/RBF'ing them). These can just be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// treated as normal funds where possible - they are only spendable by us and there is")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// no rush to claim them.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" output "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("hex_utils"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hex_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_secure_random_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note that if the type here changes our read code needs to change as well.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n fs_store"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("PENDING_SPENDABLE_OUTPUT_DIR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example where we spend straight to our BDK based wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SpendableOutputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("outputs\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" OnchainWallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" script "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("TxOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("arrayOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txOut"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u32Z"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("none")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_TransactionNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_TransactionNoneZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("arrayOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("plus")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n LDKBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Exception"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("message")]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example where we spend straight to our BDK based wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("handleEvent")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bdkManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("testnet "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("regtest\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" script "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcastTransactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("error"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("localizedDescription"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.SpendableOutputs",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("SpendableOutputs")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L802",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("SpendableOutputs")]),t._v(" bindings"),s("OutboundLink")],1)])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{408:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"closing-a-channel"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#closing-a-channel"}},[t._v("#")]),t._v(" Closing a Channel")]),t._v(" "),s("p",[t._v("Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs will be accepted on the given channel, and after additional timeout/the closing of all pending HTLCs, the channel will be closed on chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_channels")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("channel"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" channel"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("user_id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" user_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Channel not found"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example: Cooperative close")]),t._v("\nchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to close channel"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example: Unilateral close")]),t._v("\nchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("force_close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to close channel"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("close_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Result_NoneAPIErrorZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_NoneAPIErrorZ_Err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle error")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful close")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add Channel Id in bytes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add Counterparty Node Id in bytes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("closeChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" counterpartyNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Channel Closed")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("To claim Funds directly into a custom wallet like BDK wallet using a custom "),s("code",[t._v("KeysManager")]),t._v(" see the "),s("RouterLink",{attrs:{to:"/key_management/"}},[t._v("Key Management")]),t._v(" guide for more info.")],1),t._v(" "),s("h1",{attrs:{id:"spendableoutputs-event-handling"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#spendableoutputs-event-handling"}},[t._v("#")]),t._v(" SpendableOutputs Event Handling")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// SpendableOutputDescriptors, of which outputs is a vec of, are critical to keep track")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// of! While a `StaticOutput` descriptor is just an output to a static, well-known key,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// other descriptors are not currently ever regenerated for you by LDK. Once we return")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// from this method, the descriptor will be gone, and you may lose track of some funds.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Here we simply persist them to disk, with a background task running which will try")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// to spend them regularly (possibly duplicatively/RBF'ing them). These can just be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// treated as normal funds where possible - they are only spendable by us and there is")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// no rush to claim them.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" output "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("hex_utils"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hex_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_secure_random_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note that if the type here changes our read code needs to change as well.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n fs_store"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("PENDING_SPENDABLE_OUTPUT_DIR")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("encode")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example where we spend straight to our BDK based wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SpendableOutputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("outputs\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" OnchainWallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" script "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("TxOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("arrayOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txOut"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u32Z"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("None"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("none")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_TransactionNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_TransactionNoneZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("arrayOf")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("plus")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n LDKBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Exception"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("${")]),s("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("message")]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("}")])]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Example where we spend straight to our BDK based wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("handleEvent")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" outputs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bdkManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("testnet "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("regtest\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" script "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ldkManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcastTransactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("error"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("localizedDescription"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.SpendableOutputs",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("SpendableOutputs")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L802",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("SpendableOutputs")]),t._v(" bindings"),s("OutboundLink")],1)])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/43.37e0e256.js b/assets/js/44.bb90d5a8.js similarity index 99% rename from assets/js/43.37e0e256.js rename to assets/js/44.bb90d5a8.js index f4be4b513..3593d560a 100644 --- a/assets/js/43.37e0e256.js +++ b/assets/js/44.bb90d5a8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{404:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"connect-to-peers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#connect-to-peers"}},[t._v("#")]),t._v(" Connect to Peers")]),t._v(" "),s("p",[t._v("In this section you'll learn how to join the lightning network.")]),t._v(" "),s("p",[t._v("Firstly we need to have the ability to do high performance I/O operations. LDK provides default implementations for initializing all of your networking needs. If you are using Rust, you can use our simple socket handling library "),s("code",[t._v("lightning_net_tokio")]),t._v(". In Kotlin/Java you can use the "),s("code",[t._v("NioPeerHandler")]),t._v(" which uses Java's NIO I/O interface.")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for")]),t._v(": making peer connections, facilitating peer data to and from LDK")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use LDK's sample networking module")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" listen_port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9735")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" listener "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("net"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TcpListener")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.0.0.0:{}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" listen_port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tcp_stream "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" listener"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("accept")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spawn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's supplied networking battery to facilitate inbound")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// connections.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setup_inbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tcp_stream"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_std")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val nioPeerHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nio_peer_handler\nval port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9777")]),t._v("\nnioPeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind_listener")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InetSocketAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTCPPeerHandler")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9777")]),t._v("\npeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("Connections to other peers are established with "),s("code",[t._v("PeerManager")]),t._v(". You'll need to know the pubkey and address of another node that you want as a peer. Once the connection is established and the handshake is complete, "),s("code",[t._v("PeerManager")]),t._v(" will show the peer's pubkey in its list of peers.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect_outbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" connection_closed_future "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Box")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pin")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Make sure the connection is still established.")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("futures"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("poll!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Poll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ready")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Peer disconnected before handshake completed"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Poll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pending")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wait for the handshake to complete.")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_peer_node_ids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_millis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to connect to peer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Connect and wait for the handshake to complete.")]),t._v("\n val address"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InetSocketAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hostname"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n nioPeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pubkeyHex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5555")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The peer's pubkey will be present in the list of peer ids.")]),t._v("\n val peerManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peer_manager\n val peerNodeIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_peer_node_ids\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failure when connecting to a peer.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Connect and wait for the handshake to complete.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" pubKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's pubKey as byte array")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's address")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's port")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" theirNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pubKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The peer's pubkey will be present in the list of peer ids.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peerManager\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerNodeIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPeerNodeIds")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("PeerManager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("lightning-net-tokio")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("PeerManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/batteries/NioPeerHandler.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("NioPeerHandler")]),t._v(" bindings"),s("OutboundLink")],1),t._v(",\n"),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("PeerManager")]),t._v(" bindings"),s("OutboundLink")],1),t._v(",")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{409:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"connect-to-peers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#connect-to-peers"}},[t._v("#")]),t._v(" Connect to Peers")]),t._v(" "),s("p",[t._v("In this section you'll learn how to join the lightning network.")]),t._v(" "),s("p",[t._v("Firstly we need to have the ability to do high performance I/O operations. LDK provides default implementations for initializing all of your networking needs. If you are using Rust, you can use our simple socket handling library "),s("code",[t._v("lightning_net_tokio")]),t._v(". In Kotlin/Java you can use the "),s("code",[t._v("NioPeerHandler")]),t._v(" which uses Java's NIO I/O interface.")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for")]),t._v(": making peer connections, facilitating peer data to and from LDK")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// use LDK's sample networking module")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" listen_port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9735")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" listener "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("net"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TcpListener")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.0.0.0:{}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" listen_port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tcp_stream "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" listener"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("accept")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spawn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's supplied networking battery to facilitate inbound")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// connections.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("setup_inbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n tcp_stream"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_std")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val nioPeerHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("nio_peer_handler\nval port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9777")]),t._v("\nnioPeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind_listener")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InetSocketAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTCPPeerHandler")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9777")]),t._v("\npeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bind")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("Connections to other peers are established with "),s("code",[t._v("PeerManager")]),t._v(". You'll need to know the pubkey and address of another node that you want as a peer. Once the connection is established and the handshake is complete, "),s("code",[t._v("PeerManager")]),t._v(" will show the peer's pubkey in its list of peers.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_net_tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect_outbound")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" connection_closed_future "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Box")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pin")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Make sure the connection is still established.")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("futures"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("poll!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" connection_closed_future"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Poll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ready")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Peer disconnected before handshake completed"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Poll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pending")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wait for the handshake to complete.")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_peer_node_ids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("find")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("id"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("id "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_millis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Failed to connect to peer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Connect and wait for the handshake to complete.")]),t._v("\n val address"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SocketAddress")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InetSocketAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hostname"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n nioPeerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pubkeyHex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5555")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The peer's pubkey will be present in the list of peer ids.")]),t._v("\n val peerManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peer_manager\n val peerNodeIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_peer_node_ids\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IOException")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failure when connecting to a peer.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Connect and wait for the handshake to complete.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" pubKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's pubKey as byte array")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's address")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" port "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to retrieve peer's port")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("connect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" port"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" theirNodeId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pubKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The peer's pubkey will be present in the list of peer ids.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peerManager\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerNodeIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" peerManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPeerNodeIds")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("PeerManager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("lightning-net-tokio")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("PeerManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/batteries/NioPeerHandler.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("NioPeerHandler")]),t._v(" bindings"),s("OutboundLink")],1),t._v(",\n"),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("PeerManager")]),t._v(" bindings"),s("OutboundLink")],1),t._v(",")])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/44.dc05cd5e.js b/assets/js/45.a29d7104.js similarity index 99% rename from assets/js/44.dc05cd5e.js rename to assets/js/45.a29d7104.js index 7a11a4fa2..ce9723a05 100644 --- a/assets/js/44.dc05cd5e.js +++ b/assets/js/45.a29d7104.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{405:function(t,n,s){"use strict";s.r(n);var a=s(7),e=Object(a.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"handling-events"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#handling-events"}},[t._v("#")]),t._v(" Handling Events")]),t._v(" "),n("p",[t._v("LDK requires that you handle many different events throughout your app's life cycle. You can learn more by reading about our event-driven "),n("RouterLink",{attrs:{to:"/introduction/architecture/"}},[t._v("architecture")]),t._v(".")],1),t._v(" "),n("p",[t._v("To start handling events in your application, run:")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("events"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the event handler passed to BackgroundProcessor::start")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentSent")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentFailed")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rejected_by_dest "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FundingGenerationReady")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" org"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Event\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentSent"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentFailed"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FundingGenerationReady"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a funding tx to be broadcast")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-Swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentSent")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentFailed")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsFundingGenerationReady")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a funding tx to be broadcast")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[t._v("References: "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/events/enum.Event.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),n("code",[t._v("Event")]),t._v(" docs"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),n("code",[t._v("Event")]),t._v(" bindings"),n("OutboundLink")],1)])],1)}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{412:function(t,n,s){"use strict";s.r(n);var a=s(7),e=Object(a.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"handling-events"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#handling-events"}},[t._v("#")]),t._v(" Handling Events")]),t._v(" "),n("p",[t._v("LDK requires that you handle many different events throughout your app's life cycle. You can learn more by reading about our event-driven "),n("RouterLink",{attrs:{to:"/introduction/architecture/"}},[t._v("architecture")]),t._v(".")],1),t._v(" "),n("p",[t._v("To start handling events in your application, run:")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("events"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the event handler passed to BackgroundProcessor::start")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentSent")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentFailed")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rejected_by_dest "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FundingGenerationReady")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" org"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Event\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentSent"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentFailed"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FundingGenerationReady"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a funding tx to be broadcast")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-Swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentSent")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentFailed")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsFundingGenerationReady")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a funding tx to be broadcast")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[t._v("References: "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/events/enum.Event.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),n("code",[t._v("Event")]),t._v(" docs"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),n("code",[t._v("Event")]),t._v(" bindings"),n("OutboundLink")],1)])],1)}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/45.65df66a9.js b/assets/js/46.e511b353.js similarity index 99% rename from assets/js/45.65df66a9.js rename to assets/js/46.e511b353.js index a85fcbc98..d4ce4c679 100644 --- a/assets/js/45.65df66a9.js +++ b/assets/js/46.e511b353.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{407:function(t,s,n){"use strict";n.r(s);var a=n(7),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"getting-started"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting started")]),t._v(" "),s("p",[t._v("Welcome to the Lightning Development Kit documentation!")]),t._v(" "),s("p",[t._v("If you have any questions about anything related to LDK, feel free to ask our community on "),s("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub Discussions"),s("OutboundLink")],1),t._v(" or join us on "),s("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"installation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#installation"}},[t._v("#")]),t._v(" Installation")]),t._v(" "),s("p",[t._v("Add LDK to a project by configuring the respective config files:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Add the following dependencies to your cargo.toml and replace {VERSION} with the version number you want to use.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"max_level_trace"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-block-sync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rpc-client"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-invoice")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-net-tokio")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-persister")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-background-processor")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-rapid-gossip-sync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*\nFor Gradle, add the following dependency to your build.gradle and replace {VERSION} with\nthe version number you want to use.\n*/")]),t._v("\n\ndependencies "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n implementation 'org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("lightningdevkit"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("java"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("VERSION")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("'\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* To include the LDK Kotlin bindings in an Android project download the latest binary from https://github.com/lightningdevkit/ldk-garbagecollected/releases and place it in your libs directory.\nThen add to your build.gradle file:\n*/")]),t._v("\n\ndependencies "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n implementation "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fileTree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("include"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token char"}},[t._v("'*.aar'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" dir"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token char"}},[t._v("'libs'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("Example usage after installation is complete:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("chaininterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Installing LDK Swift")]),t._v(" "),s("p",[t._v("Add ldk-swift package using the Swift Package Manager.")]),t._v(" "),s("p",[t._v("To import the package, use: "),s("code",[t._v("import LightningDevKit")])])])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{410:function(t,s,n){"use strict";n.r(s);var a=n(7),e=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"getting-started"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting started")]),t._v(" "),s("p",[t._v("Welcome to the Lightning Development Kit documentation!")]),t._v(" "),s("p",[t._v("If you have any questions about anything related to LDK, feel free to ask our community on "),s("a",{attrs:{href:"https://github.com/orgs/lightningdevkit/discussions",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub Discussions"),s("OutboundLink")],1),t._v(" or join us on "),s("a",{attrs:{href:"https://discord.gg/xaYE3pDQpm",target:"_blank",rel:"noopener noreferrer"}},[t._v("Discord"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"installation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#installation"}},[t._v("#")]),t._v(" Installation")]),t._v(" "),s("p",[t._v("Add LDK to a project by configuring the respective config files:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# Add the following dependencies to your cargo.toml and replace {VERSION} with the version number you want to use.")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"max_level_trace"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-block-sync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rpc-client"')]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-invoice")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-net-tokio")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-persister")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-background-processor")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("lightning-rapid-gossip-sync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("VERSION"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/*\nFor Gradle, add the following dependency to your build.gradle and replace {VERSION} with\nthe version number you want to use.\n*/")]),t._v("\n\ndependencies "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n implementation 'org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("lightningdevkit"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("java"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("VERSION")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("'\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* To include the LDK Kotlin bindings in an Android project download the latest binary from https://github.com/lightningdevkit/ldk-garbagecollected/releases and place it in your libs directory.\nThen add to your build.gradle file:\n*/")]),t._v("\n\ndependencies "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n implementation "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fileTree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("include"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token char"}},[t._v("'*.aar'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" dir"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token char"}},[t._v("'libs'")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("Example usage after installation is complete:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("chaininterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Installing LDK Swift")]),t._v(" "),s("p",[t._v("Add ldk-swift package using the Swift Package Manager.")]),t._v(" "),s("p",[t._v("To import the package, use: "),s("code",[t._v("import LightningDevKit")])])])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/46.884731f1.js b/assets/js/47.6ac08a58.js similarity index 98% rename from assets/js/46.884731f1.js rename to assets/js/47.6ac08a58.js index 98a2d670c..e5abfe381 100644 --- a/assets/js/46.884731f1.js +++ b/assets/js/47.6ac08a58.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{406:function(t,n,e){"use strict";e.r(n);var r=e(7),o=Object(r.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"building-a-node-with-ldk"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#building-a-node-with-ldk"}},[t._v("#")]),t._v(" Building a Node with LDK")]),t._v(" "),n("h2",{attrs:{id:"learn-how-to-build-a-basic-ldk-node-from-scratch"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#learn-how-to-build-a-basic-ldk-node-from-scratch"}},[t._v("#")]),t._v(" Learn how to build a basic LDK node from scratch")]),t._v(" "),n("div",{staticClass:"custom-block tip"},[n("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),n("p",[t._v("For an integrated example of an LDK node in Rust, see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample Node"),n("OutboundLink")],1)])]),t._v(" "),n("p",[t._v("The following tutorials will show you how to build the simplest lightning node using LDK, that fufills the following tasks:")]),t._v(" "),n("ol",[n("li",[n("strong",[t._v("Connecting to Peers")])]),t._v(" "),n("li",[n("strong",[t._v("Opening Channels")])]),t._v(" "),n("li",[n("strong",[t._v("Sending Payments")])]),t._v(" "),n("li",[n("strong",[t._v("Receiving Payments")])]),t._v(" "),n("li",[n("strong",[t._v("Closing Channels")])])]),t._v(" "),n("h3",{attrs:{id:"foundational-components"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#foundational-components"}},[t._v("#")]),t._v(" Foundational Components")]),t._v(" "),n("p",[t._v("Let's start by looking at the core components we'll need to make this node work for the tasks we outlined above.")]),t._v(" "),n("ol",[n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("ChannelManager")]),n("OutboundLink")],1),t._v(", to open and close channels.")]),t._v(" "),n("li",[t._v("A networking stack (https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/index.html), for establishing TCP/IP connections to other nodes on the lightning network.")]),t._v(" "),n("li",[t._v("Payments & routing, ability to create and pay invoices.")])]),t._v(" "),n("p",[t._v("To make the above work we also need to setup a series of supporting modules, including:")]),t._v(" "),n("ol",[n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("FeeEstimator")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/logger/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Logger")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A Transaction "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Broadcaster")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.NetworkGraph.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("NetworkGraph")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/persist/trait.Persister.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Persister")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("An "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/trait.EventHandler.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("EventHandler")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A Transaction "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Filter")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("ChainMonitor")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("KeysManager")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Scorer")]),n("OutboundLink")],1)])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{411:function(t,n,e){"use strict";e.r(n);var r=e(7),o=Object(r.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"building-a-node-with-ldk"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#building-a-node-with-ldk"}},[t._v("#")]),t._v(" Building a Node with LDK")]),t._v(" "),n("h2",{attrs:{id:"learn-how-to-build-a-basic-ldk-node-from-scratch"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#learn-how-to-build-a-basic-ldk-node-from-scratch"}},[t._v("#")]),t._v(" Learn how to build a basic LDK node from scratch")]),t._v(" "),n("div",{staticClass:"custom-block tip"},[n("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),n("p",[t._v("For an integrated example of an LDK node in Rust, see the "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample Node"),n("OutboundLink")],1)])]),t._v(" "),n("p",[t._v("The following tutorials will show you how to build the simplest lightning node using LDK, that fufills the following tasks:")]),t._v(" "),n("ol",[n("li",[n("strong",[t._v("Connecting to Peers")])]),t._v(" "),n("li",[n("strong",[t._v("Opening Channels")])]),t._v(" "),n("li",[n("strong",[t._v("Sending Payments")])]),t._v(" "),n("li",[n("strong",[t._v("Receiving Payments")])]),t._v(" "),n("li",[n("strong",[t._v("Closing Channels")])])]),t._v(" "),n("h3",{attrs:{id:"foundational-components"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#foundational-components"}},[t._v("#")]),t._v(" Foundational Components")]),t._v(" "),n("p",[t._v("Let's start by looking at the core components we'll need to make this node work for the tasks we outlined above.")]),t._v(" "),n("ol",[n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("ChannelManager")]),n("OutboundLink")],1),t._v(", to open and close channels.")]),t._v(" "),n("li",[t._v("A networking stack (https://docs.rs/lightning-net-tokio/*/lightning_net_tokio/index.html), for establishing TCP/IP connections to other nodes on the lightning network.")]),t._v(" "),n("li",[t._v("Payments & routing, ability to create and pay invoices.")])]),t._v(" "),n("p",[t._v("To make the above work we also need to setup a series of supporting modules, including:")]),t._v(" "),n("ol",[n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("FeeEstimator")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/logger/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Logger")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A Transaction "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Broadcaster")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.NetworkGraph.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("NetworkGraph")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/persist/trait.Persister.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Persister")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("An "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/trait.EventHandler.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("EventHandler")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A Transaction "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Filter")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("ChainMonitor")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("KeysManager")]),n("OutboundLink")],1)]),t._v(" "),n("li",[t._v("A "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/index.html",target:"_blank",rel:"noopener noreferrer"}},[n("code",[t._v("Scorer")]),n("OutboundLink")],1)])])])}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/47.c711ae6d.js b/assets/js/48.baa928f9.js similarity index 99% rename from assets/js/47.c711ae6d.js rename to assets/js/48.baa928f9.js index 27d2044fe..d03a4c31d 100644 --- a/assets/js/47.c711ae6d.js +++ b/assets/js/48.baa928f9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{408:function(t,a,n){"use strict";n.r(a);var s=n(7),e=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"opening-a-channel"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opening-a-channel"}},[t._v("#")]),t._v(" Opening a Channel")]),t._v(" "),a("p",[t._v("Channels are the basic building blocks of the Lightning Network. With channels, you can transact not only with your immediate peers but with others on the network. Let's explore how to open a channel with LDK.")]),t._v(" "),a("p",[t._v("Now that you have a peer, you can open a channel with them using "),a("code",[t._v("ChannelManager")]),t._v(". You'll need the peer's pubkey as before along with:")]),t._v(" "),a("ul",[a("li",[t._v("the amount in sats to use when funding the channel,")]),t._v(" "),a("li",[t._v("any msats to push to your peer,")]),t._v(" "),a("li",[t._v("an id which is given back in the "),a("code",[t._v("FundingGenerationReady")]),t._v(" event,")]),t._v(" "),a("li",[t._v("an optional "),a("code",[t._v("UserConfig")]),t._v(" for overriding "),a("code",[t._v("ChannelManager")]),t._v(" defaults")])]),t._v(" "),a("p",[t._v("Channels can be announced to the network or can remain private, which is controlled via "),a("code",[t._v("UserConfig::announced_channel")]),t._v(".")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10_000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" push_msat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1_000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" user_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channel_options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelConfig")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" announced_channel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_channel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" push_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EVENT: initiated channel with peer {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to open channel: {:?}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-kotlin extra-class"},[a("pre",{pre:!0,attrs:{class:"language-kotlin"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100_000L")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" pushMsat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1_000L")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userChannelId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UInt128")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("nextLong")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// public aka announced channel")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" UserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelHandshakeConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ChannelHandshakeConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelHandshakeConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_announced_channel "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\nuserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_channel_handshake_config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelHandshakeConfig\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" createChannelResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_channel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n pubKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userConfig\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" userId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytesArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UUID")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("uuid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// public aka announced channel")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" userConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelHandshakeConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelHandshakeConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAnnouncedChannel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nuserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setChannelHandshakeConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" createChannelResults "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createChannel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\ttheirNetworkKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pubKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tchannelValueSatoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tpushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tuserChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\toverrideConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userConfig\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("h1",{attrs:{id:"fundinggenerationready-event-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#fundinggenerationready-event-handling"}},[t._v("#")]),t._v(" FundingGenerationReady Event Handling")]),t._v(" "),a("p",[t._v("At this point, an outbound channel has been initiated with your peer and it will appear in "),a("code",[t._v("ChannelManager::list_channels")]),t._v(". However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a "),a("code",[t._v("FundingGenerationReady")]),t._v(" event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),a("p",[t._v("Remember that the funding transaction must only spend "),a("a",{attrs:{href:"https://bitcoinops.org/en/topics/segregated-witness/",target:"_blank",rel:"noopener noreferrer"}},[t._v("SegWit"),a("OutboundLink")],1),t._v(" inputs.")])]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FundingGenerationReady")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttemporary_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tchannel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\toutput_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tuser_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\tbuilder\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add_recipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fee_rate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fee_rate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("enable_rbf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tbuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\t \t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" finalized "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" raw_tx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" finalized"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FundingGenerationReady")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val fundingSpk "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("output_script\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("34")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("output_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("funding_transaction_generated")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("temporary_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("counterparty_node_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n rawTx\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\nfun "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Long")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tval scriptListUByte"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UByte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval outputScript "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scriptListUByte"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outputScript"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toULong")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.0F")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("serialize")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsFundingGenerationReady")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rawOutputScript"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getOutputScript")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelValue "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getChannelValueSatoshis")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fundingTransactionGenerated")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t\ttemporaryChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTemporaryChannelId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tcounterpartyNodeId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getCounterpartyNodeId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tfundingTransaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rawTx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("serialize")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("satPerVbyte"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signOptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/events/enum.Event.html#variant.FundingGenerationReady",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("FundingGenerationReady")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L95",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java "),a("code",[t._v("FundingGenerationReady")]),t._v(" bindings"),a("OutboundLink")],1)]),t._v(" "),a("h1",{attrs:{id:"broadcasting-the-funding-transaction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#broadcasting-the-funding-transaction"}},[t._v("#")]),t._v(" Broadcasting the Funding Transaction")]),t._v(" "),a("p",[t._v("After crafting the funding transaction you'll need to send it to the Bitcoin network where it will hopefully be mined and added to the blockchain. You'll need to watch this transaction and wait for a minimum of 6 confirmations before the channel is ready to use.")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcast_transactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" server_url "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("DEFAULT_ESPLORA_SERVER_URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx_sync "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraSyncClient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("server_url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraBlockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_client")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("client")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BDK_CLIENT_STOP_GAP")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_concurrency")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BDK_CLIENT_CONCURRENCY")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tx_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_in_place")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tlocked_runtime\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_ref")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_on")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("log_error!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to broadcast transaction: {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\nobject "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("BroadcasterInterfaceInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("out "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tval esploraURL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"esplora url"')]),t._v("\n val blockchainConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Esplora")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("esploraURL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("u"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),t._v("u"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tval blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n txs"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("let "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" transactions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CoroutineScope")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Dispatchers")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("IO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("launch "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n transactions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forEach "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" txByteArray "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n val uByteArray "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" txByteArray"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n val transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uByteArray"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("LDKTAG")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The raw transaction broadcast is: ${txByteArray.toHex()}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("throw")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IllegalStateException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Broadcaster attempted to broadcast a null transaction"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyBroacaster")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcastTransactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" esploraURL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"esploraUrl"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" esploraConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" esploraURL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" concurrency"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stopGap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchainConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("esplora")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" esploraConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" blockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" txs "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transactionBytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to broadcast transaction: ')]),a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("\\(")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[t._v("error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("localizedDescription")]),a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("BroadcasterInterface")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/BroadcasterInterface.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("BroadcasterInterface")]),t._v(" bindings"),a("OutboundLink")],1)]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Keep LDK in sync")]),t._v(" "),a("p",[t._v("Remember if you are restarting and have open channels then you should "),a("RouterLink",{attrs:{to:"/building-a-node-with-ldk/setting-up-a-channel-manager/#sync-channelmonitors-and-channelmanager-to-chain-tip"}},[t._v("let LDK know about the latest channel state.")])],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{413:function(t,a,n){"use strict";n.r(a);var s=n(7),e=Object(s.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"opening-a-channel"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#opening-a-channel"}},[t._v("#")]),t._v(" Opening a Channel")]),t._v(" "),a("p",[t._v("Channels are the basic building blocks of the Lightning Network. With channels, you can transact not only with your immediate peers but with others on the network. Let's explore how to open a channel with LDK.")]),t._v(" "),a("p",[t._v("Now that you have a peer, you can open a channel with them using "),a("code",[t._v("ChannelManager")]),t._v(". You'll need the peer's pubkey as before along with:")]),t._v(" "),a("ul",[a("li",[t._v("the amount in sats to use when funding the channel,")]),t._v(" "),a("li",[t._v("any msats to push to your peer,")]),t._v(" "),a("li",[t._v("an id which is given back in the "),a("code",[t._v("FundingGenerationReady")]),t._v(" event,")]),t._v(" "),a("li",[t._v("an optional "),a("code",[t._v("UserConfig")]),t._v(" for overriding "),a("code",[t._v("ChannelManager")]),t._v(" defaults")])]),t._v(" "),a("p",[t._v("Channels can be announced to the network or can remain private, which is controlled via "),a("code",[t._v("UserConfig::announced_channel")]),t._v(".")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10_000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" push_msat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1_000")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" user_id "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channel_options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelConfig")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" announced_channel"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_channel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" push_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EVENT: initiated channel with peer {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to open channel: {:?}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-kotlin extra-class"},[a("pre",{pre:!0,attrs:{class:"language-kotlin"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100_000L")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" pushMsat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1_000L")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userChannelId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UInt128")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Random"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("nextLong")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// public aka announced channel")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" userConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" UserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelHandshakeConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ChannelHandshakeConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelHandshakeConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_announced_channel "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\nuserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_channel_handshake_config "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelHandshakeConfig\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" createChannelResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_channel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n pubKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userConfig\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" userId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytesArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UUID")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("uuid"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// public aka announced channel")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" userConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelHandshakeConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelHandshakeConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setAnnouncedChannel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nuserConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setChannelHandshakeConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" createChannelResults "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createChannel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\ttheirNetworkKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pubKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tchannelValueSatoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tpushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" pushMsat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tuserChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\toverrideConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userConfig\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("h1",{attrs:{id:"fundinggenerationready-event-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#fundinggenerationready-event-handling"}},[t._v("#")]),t._v(" FundingGenerationReady Event Handling")]),t._v(" "),a("p",[t._v("At this point, an outbound channel has been initiated with your peer and it will appear in "),a("code",[t._v("ChannelManager::list_channels")]),t._v(". However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a "),a("code",[t._v("FundingGenerationReady")]),t._v(" event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),a("p",[t._v("Remember that the funding transaction must only spend "),a("a",{attrs:{href:"https://bitcoinops.org/en/topics/segregated-witness/",target:"_blank",rel:"noopener noreferrer"}},[t._v("SegWit"),a("OutboundLink")],1),t._v(" inputs.")])]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FundingGenerationReady")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttemporary_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tchannel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\toutput_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tuser_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" builder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\tbuilder\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add_recipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fee_rate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fee_rate"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("enable_rbf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tbuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\t \t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" finalized "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" raw_tx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" finalized"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FundingGenerationReady")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val fundingSpk "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("output_script\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("34")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" fundingSpk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channel_value_satoshis"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("output_script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("funding_transaction_generated")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("temporary_channel_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("counterparty_node_id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n rawTx\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\nfun "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Long")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tval scriptListUByte"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UByte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval outputScript "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scriptListUByte"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outputScript"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toULong")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.0F")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tval rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("serialize")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// After the peer responds with an `accept_channel` message, an")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Event.FundingGenerationReady event will be generated.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsFundingGenerationReady")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rawOutputScript"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getOutputScript")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelValue "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getChannelValueSatoshis")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rawTx "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fundingTransactionGenerated")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t\ttemporaryChannelId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getTemporaryChannelId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tcounterpartyNodeId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getCounterpartyNodeId")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tfundingTransaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rawTx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("serialize")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate the funding transaction for the channel based on the channel amount")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The following uses BDK (Bitcoin Dev Kit) for on-chain logic")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("buildFundingTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("satPerVbyte"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" onchainWallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signOptions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/events/enum.Event.html#variant.FundingGenerationReady",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("FundingGenerationReady")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L95",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java "),a("code",[t._v("FundingGenerationReady")]),t._v(" bindings"),a("OutboundLink")],1)]),t._v(" "),a("h1",{attrs:{id:"broadcasting-the-funding-transaction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#broadcasting-the-funding-transaction"}},[t._v("#")]),t._v(" Broadcasting the Funding Transaction")]),t._v(" "),a("p",[t._v("After crafting the funding transaction you'll need to send it to the Bitcoin network where it will hopefully be mined and added to the blockchain. You'll need to watch this transaction and wait for a minimum of 6 confirmations before the channel is ready to use.")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcast_transactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" server_url "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("DEFAULT_ESPLORA_SERVER_URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx_sync "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraSyncClient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("server_url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraBlockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_client")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("client")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BDK_CLIENT_STOP_GAP")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_concurrency")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("BDK_CLIENT_CONCURRENCY")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tx_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("task"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_in_place")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tlocked_runtime\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_ref")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_on")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("move")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("log_error!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to broadcast transaction: {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\nobject "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("BroadcasterInterfaceInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("out "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tval esploraURL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"esplora url"')]),t._v("\n val blockchainConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Esplora")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("esploraURL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("u"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),t._v("u"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tval blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n txs"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("let "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" transactions "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CoroutineScope")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Dispatchers")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("IO")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("launch "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n transactions"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forEach "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" txByteArray "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v("\n val uByteArray "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" txByteArray"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n val transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uByteArray"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toList")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token constant"}},[t._v("LDKTAG")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The raw transaction broadcast is: ${txByteArray.toHex()}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("throw")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IllegalStateException")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Broadcaster attempted to broadcast a null transaction"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyBroacaster")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcastTransactions")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" esploraURL "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"esploraUrl"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" esploraConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EsploraConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("baseUrl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" esploraURL"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" proxy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" concurrency"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" stopGap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchainConfig "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("esplora")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" esploraConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" blockchainConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" txs "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" transaction "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transactionBytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" transaction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to broadcast transaction: ')]),a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("\\(")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[t._v("error"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("localizedDescription")]),a("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("BroadcasterInterface")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/BroadcasterInterface.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("BroadcasterInterface")]),t._v(" bindings"),a("OutboundLink")],1)]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Keep LDK in sync")]),t._v(" "),a("p",[t._v("Remember if you are restarting and have open channels then you should "),a("RouterLink",{attrs:{to:"/building-a-node-with-ldk/setting-up-a-channel-manager/#sync-channelmonitors-and-channelmanager-to-chain-tip"}},[t._v("let LDK know about the latest channel state.")])],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/48.4a965e08.js b/assets/js/49.c7f49fff.js similarity index 99% rename from assets/js/48.4a965e08.js rename to assets/js/49.c7f49fff.js index ce7c4c5f1..6929876c5 100644 --- a/assets/js/48.4a965e08.js +++ b/assets/js/49.c7f49fff.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{409:function(t,n,a){"use strict";a.r(n);var s=a(7),e=Object(s.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"receiving-payments"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#receiving-payments"}},[t._v("#")]),t._v(" Receiving Payments")]),t._v(" "),n("p",[t._v("To receive a payment, you'll need to create an invoice of your own with an\namount and description. "),n("code",[t._v("ChannelManager")]),t._v(" contains the remaining information\nneeded for the invoice. Use the provided utility to generate an invoice and\nregister a pending payment in "),n("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("utils"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_invoice_from_channelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n expiry_secs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SUCCESS: generated invoice: {}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" inv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n inv\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to create invoice: {:?}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_hash "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentHash")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_hash")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_byte_array")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\ninbound_payments"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payments"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("insert")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentInfo")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n secret"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_secret")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n status"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTLCStatus")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pending")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MillisatAmount")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" description "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')])]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" amtMsat"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3000000")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" UtilMethods"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_invoice_from_channelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKCurrency_Regtest"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u64Z"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amtMsat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n description"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u16Z"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("144")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" invoiceResult "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_Bolt11InvoiceSignOrCreationErrorZ"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_Bolt11InvoiceSignOrCreationErrorZ_OK"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" encodedInvoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoiceResult"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("createInvoiceFromChannelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelmanager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channelManager"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n nodeSigner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" myKeysManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("asNodeSigner")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amtMsat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n description"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string-literal"}},[n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Test Invoice"')])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n invoiceExpiryDeltaSecs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" expiry"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n minFinalCltvExpiryDelta"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ninvoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("toStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[t._v("While it is possible to create an invoice without using the utility,\n"),n("code",[t._v("ChannelManager")]),t._v(" will reject any incoming HTLCs for unregistered payments to\nprotect your privacy. In this case, use either "),n("code",[t._v("create_inbound_payment")]),t._v(" or\n"),n("code",[t._v("create_inbound_payment_for_hash")]),t._v(" to register a payment with "),n("code",[t._v("ChannelManager")]),t._v("\nbefore creating the invoice with the returned payment hash and/or secret.\nYou might also opt to for "),n("code",[t._v("inbound_payment")]),t._v(", useful for generating invoices for "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.PhantomKeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("phantom node payments"),n("OutboundLink")],1),t._v(" without a ChannelManager.")]),t._v(" "),n("h1",{attrs:{id:"paymentclaimable-event-handling"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#paymentclaimable-event-handling"}},[t._v("#")]),t._v(" PaymentClaimable Event Handling")]),t._v(" "),n("p",[t._v("As with sending a payment, LDK will generate an event once a payment is\nreceived. It is your responsibility to handle the "),n("code",[t._v("PaymentClaimable")]),t._v(" event by\nusing "),n("code",[t._v("ChannelManager")]),t._v(" to release the preimage and claim the funds.")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentClaimable")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n purpose"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amount_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n receiver_node_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n via_channel_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n via_user_channel_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n claim_deadline"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n onion_fields"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n counterparty_skimmed_fee_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\nEVENT: received payment from payment hash {} of {} millisatoshis"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("print!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"> "')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stdout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("flush")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_preimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" purpose "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvoicePayment")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpontaneousPayment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n channel_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claim_funds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentClaimable"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payment_hash "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" purpose "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("purpose "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" InvoicePayment\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" paymentPreimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("purpose"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payment_preimage "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Option_ThirtyTwoBytesZ"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Some"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("some\n\n channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claim_funds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentPreimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentClaimedEvent "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentClaimable")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentPreimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentClaimedEvent"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsInvoicePayment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPaymentPreimage")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claimFunds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentPreimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentPreimage"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[n("strong",[t._v("References:")]),t._v(" "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentClaimable",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),n("code",[t._v("PaymentClaimable")]),t._v(" docs"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L261",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),n("code",[t._v("PaymentClaimable")]),t._v(" bindings"),n("OutboundLink")],1)])],1)}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{414:function(t,n,a){"use strict";a.r(n);var s=a(7),e=Object(s.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"receiving-payments"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#receiving-payments"}},[t._v("#")]),t._v(" Receiving Payments")]),t._v(" "),n("p",[t._v("To receive a payment, you'll need to create an invoice of your own with an\namount and description. "),n("code",[t._v("ChannelManager")]),t._v(" contains the remaining information\nneeded for the invoice. Use the provided utility to generate an invoice and\nregister a pending payment in "),n("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("utils"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_invoice_from_channelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n expiry_secs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SUCCESS: generated invoice: {}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" inv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n inv\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to create invoice: {:?}"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_hash "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentHash")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_hash")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_byte_array")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\ninbound_payments"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payments"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("insert")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentInfo")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n secret"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_secret")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n status"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HTLCStatus")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Pending")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MillisatAmount")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amt_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" description "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"description"')])]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" amtMsat"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3000000")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" UtilMethods"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_invoice_from_channelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKCurrency_Regtest"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u64Z"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amtMsat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n description"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Option_u16Z"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("144")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" invoiceResult "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_Bolt11InvoiceSignOrCreationErrorZ"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_Bolt11InvoiceSignOrCreationErrorZ_OK"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" encodedInvoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoiceResult"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_str")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("createInvoiceFromChannelmanager")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelmanager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("channelManager"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n nodeSigner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" myKeysManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("asNodeSigner")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("logger"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" currency"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amtMsat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n description"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string-literal"}},[n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Test Invoice"')])]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n invoiceExpiryDeltaSecs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" expiry"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n minFinalCltvExpiryDelta"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ninvoice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("toStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[t._v("While it is possible to create an invoice without using the utility,\n"),n("code",[t._v("ChannelManager")]),t._v(" will reject any incoming HTLCs for unregistered payments to\nprotect your privacy. In this case, use either "),n("code",[t._v("create_inbound_payment")]),t._v(" or\n"),n("code",[t._v("create_inbound_payment_for_hash")]),t._v(" to register a payment with "),n("code",[t._v("ChannelManager")]),t._v("\nbefore creating the invoice with the returned payment hash and/or secret.\nYou might also opt to for "),n("code",[t._v("inbound_payment")]),t._v(", useful for generating invoices for "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.PhantomKeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("phantom node payments"),n("OutboundLink")],1),t._v(" without a ChannelManager.")]),t._v(" "),n("h1",{attrs:{id:"paymentclaimable-event-handling"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#paymentclaimable-event-handling"}},[t._v("#")]),t._v(" PaymentClaimable Event Handling")]),t._v(" "),n("p",[t._v("As with sending a payment, LDK will generate an event once a payment is\nreceived. It is your responsibility to handle the "),n("code",[t._v("PaymentClaimable")]),t._v(" event by\nusing "),n("code",[t._v("ChannelManager")]),t._v(" to release the preimage and claim the funds.")]),t._v(" "),n("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[n("div",{staticClass:"language-rust extra-class"},[n("pre",{pre:!0,attrs:{class:"language-rust"}},[n("code",[n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentClaimable")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n purpose"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n amount_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n receiver_node_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n via_channel_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n via_user_channel_id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n claim_deadline"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n onion_fields"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n counterparty_skimmed_fee_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"\\nEVENT: received payment from payment hash {} of {} millisatoshis"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n payment_hash"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount_msat"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("print!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"> "')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stdout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("flush")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_preimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" purpose "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvoicePayment")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpontaneousPayment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n channel_manager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claim_funds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payment_preimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[n("div",{staticClass:"language-kotlin extra-class"},[n("pre",{pre:!0,attrs:{class:"language-kotlin"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentClaimable"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payment_hash "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" purpose "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("purpose "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" InvoicePayment\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" paymentPreimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("purpose"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payment_preimage "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Option_ThirtyTwoBytesZ"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Some"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("some\n\n channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claim_funds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentPreimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[n("div",{staticClass:"language-swift extra-class"},[n("pre",{pre:!0,attrs:{class:"language-swift"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentClaimedEvent "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentClaimable")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentPreimage "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentClaimedEvent"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPurpose")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsInvoicePayment")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("getPaymentPreimage")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token omit keyword"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("claimFunds")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentPreimage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentPreimage"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),n("p",[n("strong",[t._v("References:")]),t._v(" "),n("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentClaimable",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),n("code",[t._v("PaymentClaimable")]),t._v(" docs"),n("OutboundLink")],1),t._v(", "),n("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L261",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),n("code",[t._v("PaymentClaimable")]),t._v(" bindings"),n("OutboundLink")],1)])],1)}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/5.6cd5b194.js b/assets/js/5.45554f81.js similarity index 98% rename from assets/js/5.6cd5b194.js rename to assets/js/5.45554f81.js index 05a847d0a..e9b2dcd4d 100644 --- a/assets/js/5.6cd5b194.js +++ b/assets/js/5.45554f81.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[5,8],{251:function(t,e){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},254:function(t,e,n){},255:function(t,e,n){},256:function(t,e,n){},257:function(t,e,n){},258:function(t,e,n){"use strict";n(254)},260:function(t,e,n){"use strict";var r={name:"PostMeta",props:["post"],filters:{capitalize:n(251).capitalize}},i=(n(258),n(7)),s=Object(i.a)(r,(function(){var t=this,e=t._self._c;return e("p",{staticClass:"meta"},[t._v("\n By\n\n "),t._l(t.post.frontmatter.authors,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/author/"+n}},[t._v(t._s(n))]),r!=t.post.frontmatter.authors.length-1?e("span",[t._v(", ")]):t._e()],1)})),t._v("\n\n on\n\n "+t._s(new Date(t.post.frontmatter.date).getMonth()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getDate()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getFullYear())+"\n\n - Tags:\n\n "),t._l(t.post.frontmatter.tags,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/tags/"+n}},[t._v(t._s(t._f("capitalize")(n)))]),r!=t.post.frontmatter.tags.length-1?[t._v(", ")]:t._e()],2)}))],2)}),[],!1,null,"0f148fb8",null);e.a=s.exports},265:function(t,e,n){"use strict";n(255)},266:function(t,e,n){"use strict";n(256)},267:function(t,e,n){var r=n(104),i=n(97),s=n(268),o=n(272);t.exports=function(t,e){if(null==t)return{};var n=r(o(t),(function(t){return[t]}));return e=i(e),s(t,n,(function(t,n){return e(t,n[0])}))}},268:function(t,e,n){var r=n(52),i=n(269),s=n(47);t.exports=function(t,e,n){for(var o=-1,a=e.length,u={};++o({comp:null}),computed:{page(){return this.$pagination.paginationIndex+1}},mounted(){n.e(4).then(n.t.bind(null,371,7)).then(t=>{this.comp=t.default})},methods:{clickCallback(t){const e=this.$pagination.getSpecificPageLink(t-1);this.$router.push(e)}}}),o=(n(265),n(7)),a=Object(o.a)(s,(function(){var t=this._self._c;return this.comp?t(this.comp,{tag:"component",attrs:{value:this.page,"page-count":this.$pagination.length,"click-handler":this.clickCallback,"prev-text":this.$pagination.prevText,"next-text":this.$pagination.nextText,"container-class":"pagination","page-class":"page-item"}}):this._e()}),[],!1,null,null,null).exports,u=(n(266),Object(o.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"pagination simple-pagination"},[t.$pagination.hasPrev?e("router-link",{attrs:{to:t.$pagination.prevLink}},[t._v("\n "+t._s(t.$pagination.prevText)+"\n ")]):t._e(),t._v(" "),t.$pagination.hasNext?e("router-link",{attrs:{to:t.$pagination.nextLink}},[t._v("\n "+t._s(t.$pagination.nextText)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports,n(24)),p=n.n(u),c=n(267),l=n.n(c),f={props:{title:{type:[String,Function],required:!1},issueId:{type:[String,Number],required:!1},options:{type:Object,required:!1},shortname:{type:String,required:!1},identifier:{type:String,required:!1},url:{type:String,required:!1},remote_auth_s3:{type:String,required:!1},api_key:{type:String,required:!1},sso_config:{type:Object,required:!1},language:{type:String,required:!1}},computed:{propsWithoutEmptyProperties(){return l()(this.$props,p.a)},commentProps(){return Object.assign({},this.propsWithoutEmptyProperties,this.$frontmatter.comment)},vssueProps(){return Object.assign({title:this.$page.title},this.commentProps)},disqusProps(){return Object.assign({identifier:this.$page.key},this.commentProps)}}},g=(Object(o.a)(f,(function(){var t=this._self._c;return"vssue"===this.$service.comment.service?t("Vssue",this._b({},"Vssue",this.vssueProps,!1)):"disqus"===this.$service.comment.service?t("Disqus",this._b({},"Disqus",this.disqusProps,!1)):this._e()}),[],!1,null,null,null).exports,n(251)),v={name:"IndexPost",components:{LayoutWrap:r.a,Pagination:a,PostMeta:i.a},props:["items","title"],computed:{posts(){return this.items||this.$pagination.pages.sort((t,e)=>new Date(e.frontmatter.date)-new Date(t.frontmatter.date))}},filters:{capitalize:g.capitalize}},h=(n(278),Object(o.a)(v,(function(){var t=this,e=t._self._c;return e("LayoutWrap",[e("main",{staticClass:"page"},[e("div",{staticClass:"theme-default-content"},[e("h1",[t._v(t._s(t.title||"Blog"))]),t._v(" "),t._l(t.posts,(function(n){return e("div",{key:n.path},[e("h2",{staticClass:"index-post-title"},[e("router-link",{attrs:{to:n.path}},[t._v(t._s(n.title||n.frontmatter.title))])],1),t._v(" "),e("PostMeta",{attrs:{post:n}}),t._v(" "),n.frontmatter.coverImage?e("router-link",{attrs:{to:n.path}},[e("img",{staticClass:"cover-image",attrs:{src:n.frontmatter.coverImage}})]):t._e(),t._v(" "),e("hr")],1)})),t._v(" "),t.$pagination.length>1?e("Pagination"):t._e()],2)])])}),[],!1,null,"073f78a2",null));e.default=h.exports},374:function(t,e,n){"use strict";n.r(e);var r={name:"DirectoryPagination",components:{IndexPost:n(281).default}},i=n(7),s=Object(i.a)(r,(function(){return(0,this._self._c)("IndexPost")}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[5,8],{251:function(t,e){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},254:function(t,e,n){},255:function(t,e,n){},256:function(t,e,n){},257:function(t,e,n){},258:function(t,e,n){"use strict";n(254)},260:function(t,e,n){"use strict";var r={name:"PostMeta",props:["post"],filters:{capitalize:n(251).capitalize}},i=(n(258),n(7)),s=Object(i.a)(r,(function(){var t=this,e=t._self._c;return e("p",{staticClass:"meta"},[t._v("\n By\n\n "),t._l(t.post.frontmatter.authors,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/author/"+n}},[t._v(t._s(n))]),r!=t.post.frontmatter.authors.length-1?e("span",[t._v(", ")]):t._e()],1)})),t._v("\n\n on\n\n "+t._s(new Date(t.post.frontmatter.date).getMonth()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getDate()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getFullYear())+"\n\n - Tags:\n\n "),t._l(t.post.frontmatter.tags,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/tags/"+n}},[t._v(t._s(t._f("capitalize")(n)))]),r!=t.post.frontmatter.tags.length-1?[t._v(", ")]:t._e()],2)}))],2)}),[],!1,null,"0f148fb8",null);e.a=s.exports},265:function(t,e,n){"use strict";n(255)},266:function(t,e,n){"use strict";n(256)},267:function(t,e,n){var r=n(104),i=n(97),s=n(268),o=n(272);t.exports=function(t,e){if(null==t)return{};var n=r(o(t),(function(t){return[t]}));return e=i(e),s(t,n,(function(t,n){return e(t,n[0])}))}},268:function(t,e,n){var r=n(52),i=n(269),s=n(47);t.exports=function(t,e,n){for(var o=-1,a=e.length,u={};++o({comp:null}),computed:{page(){return this.$pagination.paginationIndex+1}},mounted(){n.e(4).then(n.t.bind(null,375,7)).then(t=>{this.comp=t.default})},methods:{clickCallback(t){const e=this.$pagination.getSpecificPageLink(t-1);this.$router.push(e)}}}),o=(n(265),n(7)),a=Object(o.a)(s,(function(){var t=this._self._c;return this.comp?t(this.comp,{tag:"component",attrs:{value:this.page,"page-count":this.$pagination.length,"click-handler":this.clickCallback,"prev-text":this.$pagination.prevText,"next-text":this.$pagination.nextText,"container-class":"pagination","page-class":"page-item"}}):this._e()}),[],!1,null,null,null).exports,u=(n(266),Object(o.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"pagination simple-pagination"},[t.$pagination.hasPrev?e("router-link",{attrs:{to:t.$pagination.prevLink}},[t._v("\n "+t._s(t.$pagination.prevText)+"\n ")]):t._e(),t._v(" "),t.$pagination.hasNext?e("router-link",{attrs:{to:t.$pagination.nextLink}},[t._v("\n "+t._s(t.$pagination.nextText)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports,n(24)),p=n.n(u),c=n(267),l=n.n(c),f={props:{title:{type:[String,Function],required:!1},issueId:{type:[String,Number],required:!1},options:{type:Object,required:!1},shortname:{type:String,required:!1},identifier:{type:String,required:!1},url:{type:String,required:!1},remote_auth_s3:{type:String,required:!1},api_key:{type:String,required:!1},sso_config:{type:Object,required:!1},language:{type:String,required:!1}},computed:{propsWithoutEmptyProperties(){return l()(this.$props,p.a)},commentProps(){return Object.assign({},this.propsWithoutEmptyProperties,this.$frontmatter.comment)},vssueProps(){return Object.assign({title:this.$page.title},this.commentProps)},disqusProps(){return Object.assign({identifier:this.$page.key},this.commentProps)}}},g=(Object(o.a)(f,(function(){var t=this._self._c;return"vssue"===this.$service.comment.service?t("Vssue",this._b({},"Vssue",this.vssueProps,!1)):"disqus"===this.$service.comment.service?t("Disqus",this._b({},"Disqus",this.disqusProps,!1)):this._e()}),[],!1,null,null,null).exports,n(251)),v={name:"IndexPost",components:{LayoutWrap:r.a,Pagination:a,PostMeta:i.a},props:["items","title"],computed:{posts(){return this.items||this.$pagination.pages.sort((t,e)=>new Date(e.frontmatter.date)-new Date(t.frontmatter.date))}},filters:{capitalize:g.capitalize}},h=(n(278),Object(o.a)(v,(function(){var t=this,e=t._self._c;return e("LayoutWrap",[e("main",{staticClass:"page"},[e("div",{staticClass:"theme-default-content"},[e("h1",[t._v(t._s(t.title||"Blog"))]),t._v(" "),t._l(t.posts,(function(n){return e("div",{key:n.path},[e("h2",{staticClass:"index-post-title"},[e("router-link",{attrs:{to:n.path}},[t._v(t._s(n.title||n.frontmatter.title))])],1),t._v(" "),e("PostMeta",{attrs:{post:n}}),t._v(" "),n.frontmatter.coverImage?e("router-link",{attrs:{to:n.path}},[e("img",{staticClass:"cover-image",attrs:{src:n.frontmatter.coverImage}})]):t._e(),t._v(" "),e("hr")],1)})),t._v(" "),t.$pagination.length>1?e("Pagination"):t._e()],2)])])}),[],!1,null,"073f78a2",null));e.default=h.exports},378:function(t,e,n){"use strict";n.r(e);var r={name:"DirectoryPagination",components:{IndexPost:n(281).default}},i=n(7),s=Object(i.a)(r,(function(){return(0,this._self._c)("IndexPost")}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/49.7d0e5ffc.js b/assets/js/50.bcdfd20e.js similarity index 99% rename from assets/js/49.7d0e5ffc.js rename to assets/js/50.bcdfd20e.js index 5eb11d5b1..955ab6396 100644 --- a/assets/js/49.7d0e5ffc.js +++ b/assets/js/50.bcdfd20e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{410:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"sending-payments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sending-payments"}},[t._v("#")]),t._v(" Sending Payments")]),t._v(" "),a("p",[t._v("Lightning payments are used to pay invoices, which are typically encoded as a\nstring in accordance with BOLT 11. After parsing the invoice, you'll need to\nfind a route from your node to the recipient and then make the payment using\n"),a("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Parse the invoice.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("encoded_invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to parse invoice"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amt_pico_btc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("amount_pico_btc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: invalid invoice: must contain amount to pay"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amt_msat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" amt_pico_btc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payer_pubkey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_our_node_id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network_graph"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payee_pubkey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover_payee_pub_key")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payee_features "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("features")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cloned")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" first_hops "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_usable_channels")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" last_hops "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("route_hints")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" final_cltv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("min_final_cltv_expiry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Find a route and send the payment.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_route")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payer_pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payee_pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payee_features"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("first_hops"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("collect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("last_hops"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tamt_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" final_cltv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to find route"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_hash "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentHash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_hash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_inner")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_secret "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_secret")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cloned")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nchannel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("route"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payment_secret"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to send payment"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get an invoice from the recipient/payee")]),t._v("\nval invoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("recipientInvoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval invoiceResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice as "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_Bolt11InvoiceParseOrSemanticErrorZ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_Bolt11InvoiceParseOrSemanticErrorZ_OK")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\nval paymentParams "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UtilMethods")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_parameters_from_invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoiceResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval paymentParamsResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentParams as "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ_OK")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n\nval paymentHash "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_a\nval recipientOnion "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_b\nval paymentId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_a\nval routeParams "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_c\n\nval res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Retry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("attempts")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Payment success")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoiceStr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get an invoice from the payee")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" parsedInvoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromStr")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoiceVal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" parsedInvoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoicePaymentResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentParametersFromInvoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceVal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("guard")]),t._v(" invoicePaymentResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentParametersFromInvoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceVal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentHash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendPayment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n retryStrategy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithTimeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Payment Sent")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("h1",{attrs:{id:"paymentsent-paymentfailed-event-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#paymentsent-paymentfailed-event-handling"}},[t._v("#")]),t._v(" PaymentSent & PaymentFailed Event Handling")]),t._v(" "),a("p",[t._v("An event is generated once a payment has completed. Successful payments result\nin a "),a("code",[t._v("PaymentSent")]),t._v(" event with the preimage of the payment hash. Be sure to look\nout for a "),a("code",[t._v("PaymentFailed")]),t._v(" event, if the payment fails for some reason, and act\naccordingly.")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the event handler passed to BackgroundProcessor::start")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentSent")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentFailed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rejected_by_dest "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the `handleEvent` method of ChannelManagerPersister implementation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentSent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentFailed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the `handleEvent` method of ChannelManagerPersister implementation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentSentEvent "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentSent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentFailedEvent "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentFailed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentSent",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PaymentSent")]),t._v(" docs"),a("OutboundLink")],1),t._v(","),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentFailed",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PaymentFailed")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L464",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PaymentSent")]),t._v(" bindings"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L512",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PaymentFailed")]),t._v(" bindings"),a("OutboundLink")],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{415:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"sending-payments"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sending-payments"}},[t._v("#")]),t._v(" Sending Payments")]),t._v(" "),a("p",[t._v("Lightning payments are used to pay invoices, which are typically encoded as a\nstring in accordance with BOLT 11. After parsing the invoice, you'll need to\nfind a route from your node to the recipient and then make the payment using\n"),a("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Parse the invoice.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("encoded_invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to parse invoice"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amt_pico_btc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("amount_pico_btc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: invalid invoice: must contain amount to pay"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" amt_msat "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" amt_pico_btc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payer_pubkey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_our_node_id")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network_graph"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payee_pubkey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover_payee_pub_key")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payee_features "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("features")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cloned")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" first_hops "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("list_usable_channels")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" last_hops "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("route_hints")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" final_cltv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("min_final_cltv_expiry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Find a route and send the payment.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" route "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_route")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payer_pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payee_pubkey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payee_features"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("first_hops"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("collect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("last_hops"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tamt_msat"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" final_cltv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to find route"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_hash "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentHash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_hash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_inner")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payment_secret "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_secret")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cloned")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nchannel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("route"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("payment_secret"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: failed to send payment"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get an invoice from the recipient/payee")]),t._v("\nval invoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("recipientInvoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval invoiceResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice as "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_Bolt11InvoiceParseOrSemanticErrorZ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_Bolt11InvoiceParseOrSemanticErrorZ_OK")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\nval paymentParams "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UtilMethods")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("payment_parameters_from_invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoiceResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval paymentParamsResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentParams as "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ_OK")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n\nval paymentHash "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_a\nval recipientOnion "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_b\nval paymentId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_a\nval routeParams "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" paymentParamsResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("_c\n\nval res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_payment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Retry")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("attempts")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Payment success")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoiceStr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// get an invoice from the payee")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" parsedInvoice "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bolt11Invoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromStr")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoiceVal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" parsedInvoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" invoicePaymentResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentParametersFromInvoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceVal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("guard")]),t._v(" invoicePaymentResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentParametersFromInvoice")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" invoiceVal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentId "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" invoice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("paymentHash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendPayment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentHash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" recipientOnion"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" paymentId"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" routeParams"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n retryStrategy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithTimeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Payment Sent")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("h1",{attrs:{id:"paymentsent-paymentfailed-event-handling"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#paymentsent-paymentfailed-event-handling"}},[t._v("#")]),t._v(" PaymentSent & PaymentFailed Event Handling")]),t._v(" "),a("p",[t._v("An event is generated once a payment has completed. Successful payments result\nin a "),a("code",[t._v("PaymentSent")]),t._v(" event with the preimage of the payment hash. Be sure to look\nout for a "),a("code",[t._v("PaymentFailed")]),t._v(" event, if the payment fails for some reason, and act\naccordingly.")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the event handler passed to BackgroundProcessor::start")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" event "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentSent")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_preimage "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PaymentFailed")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" payment_hash"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rejected_by_dest "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the `handleEvent` method of ChannelManagerPersister implementation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentSent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("event is "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("PaymentFailed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In the `handleEvent` method of ChannelManagerPersister implementation")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentSentEvent "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentSent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle successful payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" paymentFailedEvent "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" event"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueAsPaymentFailed")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Handle failed payment")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentSent",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PaymentSent")]),t._v(" docs"),a("OutboundLink")],1),t._v(","),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/events/enum.Event.html#variant.PaymentFailed",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PaymentFailed")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L464",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PaymentSent")]),t._v(" bindings"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L512",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PaymentFailed")]),t._v(" bindings"),a("OutboundLink")],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/50.741dac5c.js b/assets/js/51.ef2675ae.js similarity index 99% rename from assets/js/50.741dac5c.js rename to assets/js/51.ef2675ae.js index b48006a85..bc174efcf 100644 --- a/assets/js/50.741dac5c.js +++ b/assets/js/51.ef2675ae.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{411:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"setting-up-a-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-a-channelmanager"}},[t._v("#")]),t._v(" Setting up a ChannelManager")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("ChannelManager")]),t._v(" is responsible for several tasks related to managing channel state. This includes keeping track of many channels, sending messages to appropriate channels, creating channels and more.")]),t._v(" "),s("h2",{attrs:{id:"adding-a-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#adding-a-channelmanager"}},[t._v("#")]),t._v(" Adding a ChannelManager")]),t._v(" "),s("p",[t._v("Adding a "),s("code",[t._v("ChannelManager")]),t._v(" to your application should look something like this:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("channelmanager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("entropy_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("node_signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("signer_provider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n current_timestamp\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("batteries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ChannelManagerConstructor\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scoringParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n routerWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// optional")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructionParameters "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructionParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n entropySource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asEntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n nodeSigner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asNodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n enableP2PGossip"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" scorer\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("There are a few dependencies needed to get this working. Let's walk through setting up each one so we can plug them into our "),s("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),s("h3",{attrs:{id:"initialize-the-feeestimator"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-feeestimator"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("FeeEstimator")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" estimating fees for on-chain transactions that LDK wants broadcasted.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_est_sat_per_1000_weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" confirmation_target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" confirmation_target "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Background")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch background feerate,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Normal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch normal feerate (~6 blocks)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HighPriority")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch high priority feerate")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" fee_estimator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("object "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimatorInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_est_sat_per_1000_weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_Background")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_Normal")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_HighPriority")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// return default fee rate")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nval feeEstimator"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getEstSatPer1000Weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MinAllowedNonAnchorChannelRemoteFee")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("253")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelCloseMinimum")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NonAnchorChannelFee")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OnChainSweep")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" feeEstimator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ol",[s("li",[t._v("Fees must be returned in: satoshis per 1000 weight units")]),t._v(" "),s("li",[t._v("Fees must be no smaller than 253 (equivalent to 1 satoshi/vbyte, rounded up)")]),t._v(" "),s("li",[t._v("To reduce network traffic, you may want to cache fee results rather than\nretrieving fresh ones every time")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("FeeEstimator")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/FeeEstimator.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("FeeEstimator")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-router"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-router"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("Router")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" Finds a Route for a payment between the given payer and a payee.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DefaultRouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_secure_random_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringFeeParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" networkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" NetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("P2PGossipSync")]),t._v(", "),s("code",[t._v("Logger")]),t._v(", "),s("code",[t._v("KeysManager")]),t._v(", "),s("code",[t._v("Scorer")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/router/trait.Router.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Router")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Router.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Router")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-logger"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-logger"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" LDK logging")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourLogger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Record")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" raw_log "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" log "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{} {:<5} [{}:{}] {}\\n"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OffsetDateTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now_utc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("format")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%F %T"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("level"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("module_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("line"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n raw_log\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourLogger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LoggerInterface "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("record"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Record"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourLogger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Record")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Print and/or write the log to a file")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" you'll likely want to write the logs to a file for debugging purposes.")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/logger/trait.Logger.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Logger")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Logger.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Logger")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-broadcasterinterface"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-broadcasterinterface"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("BroadcasterInterface")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" broadcasting various transactions to the bitcoin network")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourTxBroadcaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" broadcaster "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourTxBroadcaster"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" BroadcasterInterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("BroadcasterInterfaceInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("out")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txBroadcaster"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" BroadcasterInterface "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" BroadcasterInterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourTxBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroacaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcastTransactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to broadcast a list of transactions")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" broadcaster "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroacaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("BroadcasterInterface")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/BroadcasterInterface.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("BroadcasterInterface")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-persist"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-persist"}},[t._v("#")]),t._v(" Initialize "),s("code",[t._v("Persist")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" persisting "),s("code",[t._v("ChannelMonitor")]),t._v("s, which contain crucial channel data, in a timely manner")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Sign")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Persist")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourPersister")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("persist_new_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateErr")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note that monitor.encode() will get you the ChannelMonitor as a")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Vec.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("update_persisted_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateErr")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourPersister"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Persist"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PersistInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("persist_new_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OutPoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("data")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" MonitorUpdateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_NoneChannelMonitorUpdateErrZ"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_persisted_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OutPoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitorUpdate"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("data")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n updateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" MonitorUpdateId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_NoneChannelMonitorUpdateErrZ"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" persister"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Persist "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Persist"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourPersister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Persist")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("persistNewChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MonitorUpdateId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateStatus")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert the code to persist the ChannelMonitor to disk")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("updatePersistedChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MonitorUpdateId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateStatus")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert the code to persist either ChannelMonitor or ChannelMonitorUpdate to disk")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Using LDK Sample Filesystem Persistence Crate in Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FilesystemPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// import LDK sample persist crate")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FilesystemPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ldk_data_dir_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ul",[s("li",[s("code",[t._v("ChannelMonitor")]),t._v("s are objects which are capable of\nresponding to on-chain events for a given channel. Thus, you will have one\n"),s("code",[t._v("ChannelMonitor")]),t._v(" per channel. They are persisted in real-time and the "),s("code",[t._v("Persist")]),t._v("\nmethods will block progress on sending or receiving payments until they return.\nYou must ensure that "),s("code",[t._v("ChannelMonitor")]),t._v("s are durably persisted to disk before\nreturning or you may lose funds.")]),t._v(" "),s("li",[t._v("If you implement a custom persister, it's important to read the trait docs (linked in References) to make sure you satisfy the API requirements, particularly for "),s("code",[t._v("update_persisted_channel")])])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Persister")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Persist.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Persister")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"start-background-processing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#start-background-processing"}},[t._v("#")]),t._v(" Start Background Processing")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" running tasks periodically in the background to keep LDK operational.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" background_processor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BackgroundProcessor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("invoice_payer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("net_graph_msg_handler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("ChannelManager")]),t._v(", "),s("code",[t._v("ChainMonitor")]),t._v(", "),s("code",[t._v("PeerManager")]),t._v(", "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning-background-processor/*/lightning_background_processor/struct.BackgroundProcessor.html#method.start",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("BackgroundProcessor::Start")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"regularly-broadcast-node-announcement"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#regularly-broadcast-node-announcement"}},[t._v("#")]),t._v(" Regularly Broadcast Node Announcement")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if you have 1 or more public channels, you may need to announce your node and its channels occasionally. LDK will automatically announce channels when they are created, but there are no guarantees you have connected peers at that time or that your peers will propagate such announcements. The broader node-announcement message is not automatically broadcast.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" interval "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("interval")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tinterval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tick")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_node_announcement")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert your node's RGB color")]),t._v("\n\t\tnode_alias"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ldk_announced_listen_addr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("Peer Manager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html#method.broadcast_node_announcement",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("PeerManager::broadcast_node_announcement")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-the-transaction-filter"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-the-transaction-filter"}},[t._v("#")]),t._v(" Optional: Initialize the Transaction "),s("code",[t._v("Filter")])]),t._v(" "),s("p",[s("strong",[t._v("You must follow this step if:")]),t._v(" you are "),s("em",[t._v("not")]),t._v(" providing full blocks to LDK,\ni.e. if you're using BIP 157/158 or Electrum as your chain backend")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if you are not providing full blocks, LDK uses this\nobject to tell you what transactions and outputs to watch for on-chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Txid")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("usize")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("object "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FilterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nval txFilter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("registerTx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" scriptPubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to watch this transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("registerOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to watch for any transaction that spend this output")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" see the "),s("RouterLink",{attrs:{to:"/blockchain_data/introduction/"}},[t._v("Blockchain Data")]),t._v(" guide for more info")],1),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Filter")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Filter.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Filter")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-chainmonitor"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-chainmonitor"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("ChainMonitor")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" tracking one or more "),s("code",[t._v("ChannelMonitor")]),t._v("s and using them to monitor the chain for lighting transactions that are relevant to our node, and broadcasting transactions if need be.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Box")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as None or insert the Filter trait object")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chain_monitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as `null` or insert the Filter object.")]),t._v("\n\nval chainMonitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as `nil` or insert the Filter object.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chainMonitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n chainSource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" persister\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" "),s("code",[t._v("Filter")]),t._v(" must be non-"),s("code",[t._v("None")]),t._v(" if you're using Electrum or BIP 157/158 as your chain backend")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("FeeEstimator")]),t._v(", "),s("code",[t._v("Logger")]),t._v(", "),s("code",[t._v("BroadcasterInterface")]),t._v(", "),s("code",[t._v("Persist")])]),t._v(" "),s("p",[s("strong",[t._v("Optional dependency:")]),t._v(" "),s("code",[t._v("Filter")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/struct.ChainMonitor.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ChainMonitor")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ChainMonitor.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ChainMonitor")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-keysmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-keysmanager"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("KeysManager")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" providing keys for signing Lightning transactions")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_seed_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/keys_seed"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If we're restarting and already have a key seed, read it from disk. Else,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// create a new one.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("fs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("assert_eq!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy_from_slice")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n key\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("thread_rng")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fill_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write_all")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to write node keys seed to disk"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync_all")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to sync node keys seed to disk"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Unable to create keys seed file {}: {}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n key\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val keySeed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nval keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n keySeed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to create seed with random bytes or if restarting, reload the seed from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ul",[s("li",[t._v("See the "),s("RouterLink",{attrs:{to:"/key_management/"}},[t._v("Key Management")]),t._v(" guide for more info")],1),t._v(" "),s("li",[t._v("Note that you must write the "),s("code",[t._v("key_seed")]),t._v(" you give to the "),s("code",[t._v("KeysManager")]),t._v(" on\nstartup to disk, and keep using it to initialize the "),s("code",[t._v("KeysManager")]),t._v(" every time\nyou restart. This "),s("code",[t._v("key_seed")]),t._v(" is used to derive your node's secret key (which\ncorresponds to its node pubkey) and all other secret key material.")]),t._v(" "),s("li",[t._v("The current time is part of the "),s("code",[t._v("KeysManager")]),t._v("'s parameters because it is used to derive\nrandom numbers from the seed where required, to ensure all random\ngeneration is unique across restarts.")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" random bytes")]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("KeysManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/KeysManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("KeysManager")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"read-channelmonitor-state-from-disk"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#read-channelmonitor-state-from-disk"}},[t._v("#")]),t._v(" Read "),s("code",[t._v("ChannelMonitor")]),t._v(" state from disk")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if LDK is restarting and has at least 1 channel, its "),s("code",[t._v("ChannelMonitor")]),t._v("s will need to be (1) fed to the "),s("code",[t._v("ChannelManager")]),t._v(" and (2) synced to chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's sample persister crate provided method")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_monitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_channelmonitors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If you are using Electrum or BIP 157/158, you must call load_outputs_to_watch")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// on each ChannelMonitor to prepare for chain synchronization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" chan_mon "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chan_mon"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("load_outputs_to_watch")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialize the hashmap where we'll store the `ChannelMonitor`s read from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This hashmap will later be given to the `ChannelManager` on initialization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" channelMonitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arrayOf"),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nval channelMonitorList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ArrayList")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelMonitorFiles"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iterator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forEach "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val channelMonitorBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" it"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hexStringToByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n channelMonitorList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelMonitorBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nchannelMonitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelMonitorList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toTypedArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialize the array where we'll store the `ChannelMonitor`s read from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This array will later be given to the `ChannelManagerConstructor` on initialization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" allChannels "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to get a list of persisted channels")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" channel "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" allChannels "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelData "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Data")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("contentsOf"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channel"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("KeysManager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/channelmonitor/struct.ChannelMonitor.html#method.load_outputs_to_watch",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("load_outputs_to_watch")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-channelmanager"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("ChannelManager")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" managing channel state")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" user_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* RESTARTING */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_manager_file "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("fs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/manager"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the `ChannelMonitors` we read from disk.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_monitor_mut_references "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter_mut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channel_monitor_mut_references"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" read_args "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerReadArgs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channel_monitor_mut_references"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager_file"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" read_args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* FRESH CHANNELMANAGER */")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" best_blockhash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert the best blockhash you know of")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" best_chain_height "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert the height corresponding to best_blockhash")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chain_params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainParameters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// substitute this with your network")]),t._v("\n best_block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("best_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" best_chain_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" fresh_channel_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("entropy_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("node_signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("signer_provider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n current_timestamp\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("best_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fresh_channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serializedChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isNotEmpty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Loading from disk (restarting)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txFilter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringFeeParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fresh start")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringFeeParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" serializedChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelManagerSerialized"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelMonitorsSerialized"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraphArgument")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("instance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" No methods should be called on "),s("code",[t._v("ChannelManager")]),t._v(" until\n"),s("em",[t._v("after")]),t._v(" the "),s("code",[t._v("ChannelMonitor")]),t._v("s and "),s("code",[t._v("ChannelManager")]),t._v(" are synced to the chain tip (next step).")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("KeysManager")]),t._v(", "),s("code",[t._v("FeeEstimator")]),t._v(", "),s("code",[t._v("ChainMonitor")]),t._v(", "),s("code",[t._v("BroadcasterInterface")]),t._v(", "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ChannelManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ChannelManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ChannelManager")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"sync-channelmonitors-and-channelmanager-to-chain-tip"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sync-channelmonitors-and-channelmanager-to-chain-tip"}},[t._v("#")]),t._v(" Sync "),s("code",[t._v("ChannelMonitor")]),t._v("s and "),s("code",[t._v("ChannelManager")]),t._v(" to chain tip")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" this step is only necessary if you're restarting and have open channels. This step ensures that LDK channel state is up-to-date with the bitcoin blockchain")]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Full Blocks or BIP 157/158")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("init"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("poll"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UnboundedCache")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockSource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourChainBackend")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_header")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height_hint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHeaderData")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_best_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" block_source "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourChainBackend")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_listener_channel_monitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" cache "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UnboundedCache")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_tip"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("poll"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ValidatedBlockHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_listeners "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Listen")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("drain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" outpoint "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_funding_txo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n chain_listener_channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" monitor_listener_info "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" chain_listener_channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter_mut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain_listeners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n monitor_listener_info"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" monitor_listener_info"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Listen")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Save the chain tip to be used in future steps")]),t._v("\nchain_tip "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("init"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("synchronize_listeners")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" block_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" cache"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_listeners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Electrum/Esplora")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transaction IDs to check the chain for un-confirmation.")]),t._v("\nval relevantTxIdsFromChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Confirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_relevant_txids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval relevantTxIdsFromChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Confirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_relevant_txids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval relevantTxIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" relevantTxIdsFromChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" relevantTxIdsFromChainMonitor\n\nval unconfirmedTxs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid in unconfirmedTxs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transaction_unconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transaction_unconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transactions and outputs that were registered through the `Filter`")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interface.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If any of these txs/outputs were confirmed on-chain, then:")]),t._v("\nval header"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert block header from the block with confirmed tx/output")]),t._v("\nval height"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert block height of `header`")]),t._v("\nval txIndex"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Long")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert tx index in block")]),t._v("\nval serializedTx"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert tx hex as byte array")]),t._v("\nval tx"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" serializedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Marshall all TwoTuples you built right above into an array")]),t._v("\nval txList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arrayOf"),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactions_confirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactions_confirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nval bestHeader"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nval bestHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_best_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_best_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finally, tell LDK that chain sync is complete. This will also spawn several")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// background threads to handle networking and event processing.")]),t._v("\nchannelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("chain_sync_completed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("customEventHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Electrum/Esplora")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transaction IDs to check the chain for un-confirmation.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" relevantTxIds1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRelevantTxids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("??")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" relevantTxIds2 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRelevantTxids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("??")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" relevantTxIds1 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" relevantTxIds2 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" unconfirmedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to find out from your chain source")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if any of relevantTxIds have been reorged out")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// of the chain")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" txid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" unconfirmedTx "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionUnconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionUnconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transactions and outputs that were registered through the `Filter` interface.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" confirmedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to find out from your chain source")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if any of the `Filter` txs/outputs were confirmed")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// on-chain")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" txid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" confirmedTx "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch header")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch height of the header")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch tx")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch tx index")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionsConfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txdata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionsConfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txdata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bestHeader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch best header")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bestHeight "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch best height")]),t._v("\n\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bestBlockUpdated")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bestBlockUpdated")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finally, tell LDK that chain sync is complete. This will also spawn several")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// background threads to handle networking and event processing.")]),t._v("\nchannelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("chainSyncCompleted")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerPersister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("p",[t._v("There are 2 main options for synchronizing to chain on startup:")]),t._v(" "),s("p",[s("strong",[t._v("Full Blocks or BIP 157/158")])]),t._v(" "),s("p",[t._v("If you are connecting full blocks or using BIP 157/158, then it is recommended to use\nLDK's "),s("code",[t._v("lightning_block_sync")]),t._v(" crate as in the example above: the high-level steps that must be done for both "),s("code",[t._v("ChannelManager")]),t._v(" and each "),s("code",[t._v("ChannelMonitor")]),t._v(" are as follows:")]),t._v(" "),s("ol",[s("li",[t._v("Get the last blockhash that each object saw.\n"),s("ul",[s("li",[t._v("Receive the latest block hash when through "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManagerReadArgs.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("deserializtion"),s("OutboundLink")],1),t._v(" of the "),s("code",[t._v("ChannelManager")]),t._v(" via "),s("code",[t._v("read()")])]),t._v(" "),s("li",[t._v("Each "),s("code",[t._v("ChannelMonitor")]),t._v("'s is in "),s("code",[t._v("channel_manager.channel_monitors")]),t._v(", as the 2nd element in each tuple")])])]),t._v(" "),s("li",[t._v("For each object, if its latest known blockhash has been reorged out of the chain, then disconnect blocks using "),s("code",[t._v("channel_manager.as_Listen().block_disconnected(..)")]),t._v(" or "),s("code",[t._v("channel_monitor.block_disconnected(..)")]),t._v(" until you reach the last common ancestor with the main chain.")]),t._v(" "),s("li",[t._v("For each object, reconnect blocks starting from the common ancestor until it gets to your best known chain tip using "),s("code",[t._v("channel_manager.as_Listen().block_connected(..)")]),t._v(" and/or "),s("code",[t._v("channel_monitor.block_connected(..)")]),t._v(".")]),t._v(" "),s("li",[t._v("Call "),s("code",[t._v("channel_manager.chain_sync_completed(..)")]),t._v(" to complete the initial sync process.")])]),t._v(" "),s("p",[s("strong",[t._v("Electrum/Esplora")])]),t._v(" "),s("p",[t._v("Alternatively, you can use LDK's "),s("code",[t._v("lightning-transaction-sync")]),t._v(" crate. This provides utilities for syncing LDK via the transaction-based "),s("code",[t._v("Confirm")]),t._v(" interface.")]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-p2pgossipsync-or-rapidgossipsync"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-p2pgossipsync-or-rapidgossipsync"}},[t._v("#")]),t._v(" Optional: Initialize "),s("code",[t._v("P2PGossipSync or RapidGossipSync")])]),t._v(" "),s("p",[s("strong",[t._v("You must follow this step if:")]),t._v(" you need LDK to provide routes for sending payments (i.e. you are "),s("em",[t._v("not")]),t._v(" providing your own routes)")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" generating routes to send payments over")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" genesis "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("genesis_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/network_graph"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" genesis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" gossip_sync "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Access")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Send")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Sync")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val genesisBlock "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_genesis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval genesisBlockHash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byteArrayToHex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("genesisBlock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nval serializedNetworkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read network graph bytes from file")]),t._v("\nval networkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serializedNetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval p2pGossip "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option_AccessZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("none")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Network Graph exists, then read from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedNetworkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read Network Graph bytes from file")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" readResult "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedNetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" arg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" readResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" readResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Network Graph does not exist, create a new one")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialise RGS")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rgs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RapidGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lastSync "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getLastRapidGossipSyncTimestamp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" snapshot "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" lastSync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateNetworkGraphNoStd")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("updateData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" snapshot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" currentTimeUnix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"RGS updated"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" snapshot "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use lastSyncTimeStamp as 0 for first Sync")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateNetworkGraphNoStd")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("updateData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" snapshot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" currentTimeUnix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"RGS initialized for the first time"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get current snapshot from the RGS Server")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's RGS Server or use your own Server")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("URL")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("string"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://rapidsync.lightningdevkit.org/snapshot/')]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("\\(")]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[t._v("lastSyncTimeStamp")]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the url to get the data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" this struct is not required if you are providing your own routes. It will be used internally in "),s("code",[t._v("ChannelManager")]),t._v(" to build a "),s("code",[t._v("NetworkGraph")]),t._v(". Network options include: "),s("code",[t._v("Mainnet")]),t._v(","),s("code",[t._v("Regtest")]),t._v(","),s("code",[t._v("Testnet")]),t._v(","),s("code",[t._v("Signet")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("Optional dependency:")]),t._v(" "),s("code",[t._v("Access")]),t._v(", a source of chain information. Recommended to be able to verify channels before adding them to the internal network graph.")]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.P2PGossipSync.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("P2PGossipSync")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Access.html",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("Access")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/P2PGossipSync.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("P2PGossipSync")]),t._v(" bindings"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/*/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("RapidGossipSync")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/RapidGossipSync.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("RapidGossipSync")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-probabilistic-scorer"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-probabilistic-scorer"}},[t._v("#")]),t._v(" Optional: Initialize "),s("code",[t._v("Probabilistic Scorer")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for")]),t._v(": to find a suitable payment path to reach the destination.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/network_graph"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/scorer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RwLock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_scorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("scorer_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerFile"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" scorerReaderResult "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerFile"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("readBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerReaderResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerReaderResult "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_ProbabilisticScorerDecodeErrorZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_ProbabilisticScorerDecodeErrorZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Probabilistic Scorer loaded and running"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Couldn\'t load Probabilistic Scorer"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Creating a new Probabilistic Scorer"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Scorer exists, then read from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read Scorer bytes from file")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringDecayParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedProbabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n ser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argA"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argB"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" serializedProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" score "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Scorer loaded")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MultiThreadedLockableScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Scorer does not exist, create a new one")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringDecayParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" score "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Scorer loaded")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MultiThreadedLockableScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("NetworkGraph")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/struct.ProbabilisticScorer.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ProbabilisticScorer")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ProbabilisticScorer.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ProbabilisticScorer")]),t._v(" docs"),s("OutboundLink")],1)])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{417:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"setting-up-a-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-a-channelmanager"}},[t._v("#")]),t._v(" Setting up a ChannelManager")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("ChannelManager")]),t._v(" is responsible for several tasks related to managing channel state. This includes keeping track of many channels, sending messages to appropriate channels, creating channels and more.")]),t._v(" "),s("h2",{attrs:{id:"adding-a-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#adding-a-channelmanager"}},[t._v("#")]),t._v(" Adding a ChannelManager")]),t._v(" "),s("p",[t._v("Adding a "),s("code",[t._v("ChannelManager")]),t._v(" to your application should look something like this:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("channelmanager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("entropy_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("node_signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("signer_provider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n current_timestamp\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" org"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("batteries"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ChannelManagerConstructor\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scoringParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n routerWrapper"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// optional")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructionParameters "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructionParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n entropySource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asEntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n nodeSigner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asNodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" keysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n enableP2PGossip"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" scorer\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[t._v("There are a few dependencies needed to get this working. Let's walk through setting up each one so we can plug them into our "),s("code",[t._v("ChannelManager")]),t._v(".")]),t._v(" "),s("h3",{attrs:{id:"initialize-the-feeestimator"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-feeestimator"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("FeeEstimator")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" estimating fees for on-chain transactions that LDK wants broadcasted.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_est_sat_per_1000_weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" confirmation_target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" confirmation_target "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Background")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch background feerate,")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Normal")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch normal feerate (~6 blocks)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("HighPriority")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch high priority feerate")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can add the code here for this case")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" fee_estimator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("object "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimatorInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_est_sat_per_1000_weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_Background")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_Normal")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKConfirmationTarget_HighPriority")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// return default fee rate")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nval feeEstimator"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FeeEstimator")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getEstSatPer1000Weight")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("confirmationTarget"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfirmationTarget")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MinAllowedNonAnchorChannelRemoteFee")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("253")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelCloseMinimum")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NonAnchorChannelFee")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" confirmationTarget "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OnChainSweep")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7500")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" feeEstimator "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFeeEstimator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ol",[s("li",[t._v("Fees must be returned in: satoshis per 1000 weight units")]),t._v(" "),s("li",[t._v("Fees must be no smaller than 253 (equivalent to 1 satoshi/vbyte, rounded up)")]),t._v(" "),s("li",[t._v("To reduce network traffic, you may want to cache fee results rather than\nretrieving fresh ones every time")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("FeeEstimator")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/FeeEstimator.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("FeeEstimator")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-router"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-router"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("Router")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" Finds a Route for a payment between the given payer and a payee.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DefaultRouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_secure_random_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringFeeParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" networkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" NetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("P2PGossipSync")]),t._v(", "),s("code",[t._v("Logger")]),t._v(", "),s("code",[t._v("KeysManager")]),t._v(", "),s("code",[t._v("Scorer")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/router/trait.Router.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Router")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Router.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Router")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-logger"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-logger"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" LDK logging")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourLogger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Record")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" raw_log "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" log "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{} {:<5} [{}:{}] {}\\n"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OffsetDateTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now_utc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("format")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%F %T"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("level"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("module_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("line"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n raw_log\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourLogger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LoggerInterface "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("record"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Record"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourLogger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Logger")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("log")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("record"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Record")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Print and/or write the log to a file")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" logger "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyLogger")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" you'll likely want to write the logs to a file for debugging purposes.")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/util/logger/trait.Logger.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Logger")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Logger.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Logger")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-broadcasterinterface"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-broadcasterinterface"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("BroadcasterInterface")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" broadcasting various transactions to the bitcoin network")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourTxBroadcaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" broadcaster "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroadcaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourTxBroadcaster"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" BroadcasterInterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("BroadcasterInterfaceInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_transactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("out")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" txBroadcaster"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" BroadcasterInterface "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" BroadcasterInterface"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourTxBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroacaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BroadcasterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("broadcastTransactions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to broadcast a list of transactions")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" broadcaster "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxBroacaster")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("BroadcasterInterface")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/BroadcasterInterface.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("BroadcasterInterface")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-persist"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-persist"}},[t._v("#")]),t._v(" Initialize "),s("code",[t._v("Persist")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" persisting "),s("code",[t._v("ChannelMonitor")]),t._v("s, which contain crucial channel data, in a timely manner")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Sign")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Persist")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourPersister")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("persist_new_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateErr")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note that monitor.encode() will get you the ChannelMonitor as a")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Vec.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("update_persisted_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelSigner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateErr")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("object")]),t._v(" YourPersister"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Persist"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("PersistInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("persist_new_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OutPoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("data")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" MonitorUpdateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_NoneChannelMonitorUpdateErrZ"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_persisted_channel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" OutPoint"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitorUpdate"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("data")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ChannelMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n updateId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" MonitorUpdateId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_NoneChannelMonitorUpdateErrZ"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" persister"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Persist "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Persist"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("YourPersister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Persist")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("persistNewChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MonitorUpdateId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateStatus")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert the code to persist the ChannelMonitor to disk")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("updatePersistedChannel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("OutPoint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" updateId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MonitorUpdateId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelMonitorUpdateStatus")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert the code to persist either ChannelMonitor or ChannelMonitorUpdate to disk")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Using LDK Sample Filesystem Persistence Crate in Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FilesystemPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// import LDK sample persist crate")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" persister "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FilesystemPersister")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ldk_data_dir_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ul",[s("li",[s("code",[t._v("ChannelMonitor")]),t._v("s are objects which are capable of\nresponding to on-chain events for a given channel. Thus, you will have one\n"),s("code",[t._v("ChannelMonitor")]),t._v(" per channel. They are persisted in real-time and the "),s("code",[t._v("Persist")]),t._v("\nmethods will block progress on sending or receiving payments until they return.\nYou must ensure that "),s("code",[t._v("ChannelMonitor")]),t._v("s are durably persisted to disk before\nreturning or you may lose funds.")]),t._v(" "),s("li",[t._v("If you implement a custom persister, it's important to read the trait docs (linked in References) to make sure you satisfy the API requirements, particularly for "),s("code",[t._v("update_persisted_channel")])])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Persister")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Persist.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Persister")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"start-background-processing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#start-background-processing"}},[t._v("#")]),t._v(" Start Background Processing")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" running tasks periodically in the background to keep LDK operational.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" background_processor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BackgroundProcessor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("start")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("invoice_payer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("net_graph_msg_handler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("peer_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("ChannelManager")]),t._v(", "),s("code",[t._v("ChainMonitor")]),t._v(", "),s("code",[t._v("PeerManager")]),t._v(", "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning-background-processor/*/lightning_background_processor/struct.BackgroundProcessor.html#method.start",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("BackgroundProcessor::Start")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"regularly-broadcast-node-announcement"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#regularly-broadcast-node-announcement"}},[t._v("#")]),t._v(" Regularly Broadcast Node Announcement")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if you have 1 or more public channels, you may need to announce your node and its channels occasionally. LDK will automatically announce channels when they are created, but there are no guarantees you have connected peers at that time or that your peers will propagate such announcements. The broader node-announcement message is not automatically broadcast.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" interval "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("tokio"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("interval")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Duration")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("60")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("loop")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tinterval"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("tick")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\tchannel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast_node_announcement")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert your node's RGB color")]),t._v("\n\t\tnode_alias"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("ldk_announced_listen_addr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("Peer Manager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html#method.broadcast_node_announcement",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("PeerManager::broadcast_node_announcement")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-the-transaction-filter"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-the-transaction-filter"}},[t._v("#")]),t._v(" Optional: Initialize the Transaction "),s("code",[t._v("Filter")])]),t._v(" "),s("p",[s("strong",[t._v("You must follow this step if:")]),t._v(" you are "),s("em",[t._v("not")]),t._v(" providing full blocks to LDK,\ni.e. if you're using BIP 157/158 or Electrum as your chain backend")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if you are not providing full blocks, LDK uses this\nobject to tell you what transactions and outputs to watch for on-chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Txid")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("usize")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("object "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FilterInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" script_pubkey"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n override fun "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("register_output")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nval txFilter"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourTxFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("registerTx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" scriptPubkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to watch this transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("registerOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("output"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WatchedOutput")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to watch for any transaction that spend this output")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyFilter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" see the "),s("RouterLink",{attrs:{to:"/blockchain_data/introduction/"}},[t._v("Blockchain Data")]),t._v(" guide for more info")],1),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("em",[t._v("none")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("Filter")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Filter.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("Filter")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-chainmonitor"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-chainmonitor"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("ChainMonitor")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" tracking one or more "),s("code",[t._v("ChannelMonitor")]),t._v("s and using them to monitor the chain for lighting transactions that are relevant to our node, and broadcasting transactions if need be.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Box")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as None or insert the Filter trait object")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chain_monitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val filter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as `null` or insert the Filter object.")]),t._v("\n\nval chainMonitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// leave this as `nil` or insert the Filter object.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chainMonitor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainMonitor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n chainSource"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" persister\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" "),s("code",[t._v("Filter")]),t._v(" must be non-"),s("code",[t._v("None")]),t._v(" if you're using Electrum or BIP 157/158 as your chain backend")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("FeeEstimator")]),t._v(", "),s("code",[t._v("Logger")]),t._v(", "),s("code",[t._v("BroadcasterInterface")]),t._v(", "),s("code",[t._v("Persist")])]),t._v(" "),s("p",[s("strong",[t._v("Optional dependency:")]),t._v(" "),s("code",[t._v("Filter")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chainmonitor/struct.ChainMonitor.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ChainMonitor")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ChainMonitor.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ChainMonitor")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-keysmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-keysmanager"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("KeysManager")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" providing keys for signing Lightning transactions")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_seed_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/keys_seed"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If we're restarting and already have a key seed, read it from disk. Else,")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// create a new one.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("fs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("assert_eq!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy_from_slice")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n key\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("thread_rng")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fill_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write_all")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to write node keys seed to disk"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n f"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync_all")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to sync node keys seed to disk"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ERROR: Unable to create keys seed file {}: {}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keys_seed_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n key\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val keySeed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nval keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n keySeed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("System")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to create seed with random bytes or if restarting, reload the seed from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("ul",[s("li",[t._v("See the "),s("RouterLink",{attrs:{to:"/key_management/"}},[t._v("Key Management")]),t._v(" guide for more info")],1),t._v(" "),s("li",[t._v("Note that you must write the "),s("code",[t._v("key_seed")]),t._v(" you give to the "),s("code",[t._v("KeysManager")]),t._v(" on\nstartup to disk, and keep using it to initialize the "),s("code",[t._v("KeysManager")]),t._v(" every time\nyou restart. This "),s("code",[t._v("key_seed")]),t._v(" is used to derive your node's secret key (which\ncorresponds to its node pubkey) and all other secret key material.")]),t._v(" "),s("li",[t._v("The current time is part of the "),s("code",[t._v("KeysManager")]),t._v("'s parameters because it is used to derive\nrandom numbers from the seed where required, to ensure all random\ngeneration is unique across restarts.")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" random bytes")]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("KeysManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/KeysManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("KeysManager")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"read-channelmonitor-state-from-disk"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#read-channelmonitor-state-from-disk"}},[t._v("#")]),t._v(" Read "),s("code",[t._v("ChannelMonitor")]),t._v(" state from disk")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" if LDK is restarting and has at least 1 channel, its "),s("code",[t._v("ChannelMonitor")]),t._v("s will need to be (1) fed to the "),s("code",[t._v("ChannelManager")]),t._v(" and (2) synced to chain.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's sample persister crate provided method")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_monitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_channelmonitors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If you are using Electrum or BIP 157/158, you must call load_outputs_to_watch")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// on each ChannelMonitor to prepare for chain synchronization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" chan_mon "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chan_mon"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("load_outputs_to_watch")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialize the hashmap where we'll store the `ChannelMonitor`s read from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This hashmap will later be given to the `ChannelManager` on initialization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" channelMonitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arrayOf"),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nval channelMonitorList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ArrayList")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchannelMonitorFiles"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iterator")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("forEach "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n val channelMonitorBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" it"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hexStringToByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n channelMonitorList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelMonitorBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nchannelMonitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelMonitorList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toTypedArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialize the array where we'll store the `ChannelMonitor`s read from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This array will later be given to the `ChannelManagerConstructor` on initialization.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" allChannels "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to get a list of persisted channels")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" channel "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" allChannels "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelData "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Data")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("contentsOf"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channel"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelBytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelBytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("KeysManager")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/channelmonitor/struct.ChannelMonitor.html#method.load_outputs_to_watch",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("load_outputs_to_watch")]),t._v(" docs"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"initialize-the-channelmanager"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#initialize-the-channelmanager"}},[t._v("#")]),t._v(" Initialize the "),s("code",[t._v("ChannelManager")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" managing channel state")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" user_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* RESTARTING */")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channel_manager_file "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("fs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("File")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/manager"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the `ChannelMonitors` we read from disk.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_monitor_mut_references "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter_mut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channel_monitor_mut_references"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" read_args "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerReadArgs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channel_monitor_mut_references"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager_file"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" read_args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* FRESH CHANNELMANAGER */")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" best_blockhash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert the best blockhash you know of")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" best_chain_height "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert the height corresponding to best_blockhash")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" chain_params "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChainParameters")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// substitute this with your network")]),t._v("\n best_block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("best_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" best_chain_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" fresh_channel_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("chain_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("entropy_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("node_signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("signer_provider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n user_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n current_timestamp\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("best_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fresh_channel_manager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serializedChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isNotEmpty")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Loading from disk (restarting)")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txFilter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringFeeParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n scorer"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fresh start")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Regtest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userConfig"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_EntropySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_NodeSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_impl")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feeEstimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ProbabilisticScoringFeeParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n txBroadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" serializedChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelManagerSerialized"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelMonitorsSerialized"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedChannelMonitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraphArgument")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("instance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" filter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" channelManagerConstructor "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChannelManagerConstructor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHash"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n currentBlockchainTipHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" latestBlockHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerConstructionParameters\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" No methods should be called on "),s("code",[t._v("ChannelManager")]),t._v(" until\n"),s("em",[t._v("after")]),t._v(" the "),s("code",[t._v("ChannelMonitor")]),t._v("s and "),s("code",[t._v("ChannelManager")]),t._v(" are synced to the chain tip (next step).")]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("KeysManager")]),t._v(", "),s("code",[t._v("FeeEstimator")]),t._v(", "),s("code",[t._v("ChainMonitor")]),t._v(", "),s("code",[t._v("BroadcasterInterface")]),t._v(", "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ChannelManager")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ChannelManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ChannelManager")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"sync-channelmonitors-and-channelmanager-to-chain-tip"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sync-channelmonitors-and-channelmanager-to-chain-tip"}},[t._v("#")]),t._v(" Sync "),s("code",[t._v("ChannelMonitor")]),t._v("s and "),s("code",[t._v("ChannelManager")]),t._v(" to chain tip")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" this step is only necessary if you're restarting and have open channels. This step ensures that LDK channel state is up-to-date with the bitcoin blockchain")]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Full Blocks or BIP 157/158")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("init"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("poll"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UnboundedCache")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning_block_sync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockSource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourChainBackend")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_header")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height_hint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHeaderData")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" header_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_best_block")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AsyncBlockSourceResult")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" block_source "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("YourChainBackend")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_listener_channel_monitors "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" cache "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UnboundedCache")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_tip"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("poll"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ValidatedBlockHeader")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" chain_listeners "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_manager_blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" channel_manager "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Listen")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("drain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" outpoint "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_funding_txo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n chain_listener_channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n blockhash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channel_monitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("broadcaster"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("fee_estimator"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outpoint"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" monitor_listener_info "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" chain_listener_channel_monitors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter_mut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain_listeners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n monitor_listener_info"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" monitor_listener_info"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Listen")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Save the chain tip to be used in future steps")]),t._v("\nchain_tip "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("init"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("synchronize_listeners")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" block_source"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" cache"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n chain_listeners"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Electrum/Esplora")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transaction IDs to check the chain for un-confirmation.")]),t._v("\nval relevantTxIdsFromChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Confirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_relevant_txids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval relevantTxIdsFromChannelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Confirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_relevant_txids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval relevantTxIds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" relevantTxIdsFromChannelManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" relevantTxIdsFromChainMonitor\n\nval unconfirmedTxs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid in unconfirmedTxs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transaction_unconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transaction_unconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transactions and outputs that were registered through the `Filter`")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interface.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If any of these txs/outputs were confirmed on-chain, then:")]),t._v("\nval header"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert block header from the block with confirmed tx/output")]),t._v("\nval height"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert block height of `header`")]),t._v("\nval txIndex"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Long")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert tx index in block")]),t._v("\nval serializedTx"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// insert tx hex as byte array")]),t._v("\nval tx"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" serializedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Marshall all TwoTuples you built right above into an array")]),t._v("\nval txList "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" arrayOf"),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TwoTuple_usizeTransactionZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactions_confirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactions_confirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txList"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nval bestHeader"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Array")]),s("span",{pre:!0,attrs:{class:"token generics"}},[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nval bestHeight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Int")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ")]),t._v("\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_best_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("update_best_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finally, tell LDK that chain sync is complete. This will also spawn several")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// background threads to handle networking and event processing.")]),t._v("\nchannelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("chain_sync_completed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("customEventHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Electrum/Esplora")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transaction IDs to check the chain for un-confirmation.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" relevantTxIds1 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRelevantTxids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("??")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" relevantTxIds2 "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" chainMonitor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getRelevantTxids")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("??")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" relevantTxIds1 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" relevantTxIds2 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n relevantTxIds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" unconfirmedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to find out from your chain source")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if any of relevantTxIds have been reorged out")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// of the chain")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" txid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" unconfirmedTx "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionUnconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionUnconfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txid"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve transactions and outputs that were registered through the `Filter` interface.")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" confirmedTx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to find out from your chain source")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if any of the `Filter` txs/outputs were confirmed")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// on-chain")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" txid "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" confirmedTx "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch header")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch height of the header")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch tx")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch tx index")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("txIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n channelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionsConfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txdata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n chainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("transactionsConfirmed")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" txdata"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" twoTuple"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bestHeader "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch best header")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bestHeight "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Insert code to fetch best height")]),t._v("\n\nchannelManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bestBlockUpdated")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nchainMonitor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asConfirm")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("bestBlockUpdated")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bestHeight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finally, tell LDK that chain sync is complete. This will also spawn several")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// background threads to handle networking and event processing.")]),t._v("\nchannelManagerConstructor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("chainSyncCompleted")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("persister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelManagerPersister"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")])]),t._v(" "),s("p",[t._v("There are 2 main options for synchronizing to chain on startup:")]),t._v(" "),s("p",[s("strong",[t._v("Full Blocks or BIP 157/158")])]),t._v(" "),s("p",[t._v("If you are connecting full blocks or using BIP 157/158, then it is recommended to use\nLDK's "),s("code",[t._v("lightning_block_sync")]),t._v(" crate as in the example above: the high-level steps that must be done for both "),s("code",[t._v("ChannelManager")]),t._v(" and each "),s("code",[t._v("ChannelMonitor")]),t._v(" are as follows:")]),t._v(" "),s("ol",[s("li",[t._v("Get the last blockhash that each object saw.\n"),s("ul",[s("li",[t._v("Receive the latest block hash when through "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/channelmanager/struct.ChannelManagerReadArgs.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("deserializtion"),s("OutboundLink")],1),t._v(" of the "),s("code",[t._v("ChannelManager")]),t._v(" via "),s("code",[t._v("read()")])]),t._v(" "),s("li",[t._v("Each "),s("code",[t._v("ChannelMonitor")]),t._v("'s is in "),s("code",[t._v("channel_manager.channel_monitors")]),t._v(", as the 2nd element in each tuple")])])]),t._v(" "),s("li",[t._v("For each object, if its latest known blockhash has been reorged out of the chain, then disconnect blocks using "),s("code",[t._v("channel_manager.as_Listen().block_disconnected(..)")]),t._v(" or "),s("code",[t._v("channel_monitor.block_disconnected(..)")]),t._v(" until you reach the last common ancestor with the main chain.")]),t._v(" "),s("li",[t._v("For each object, reconnect blocks starting from the common ancestor until it gets to your best known chain tip using "),s("code",[t._v("channel_manager.as_Listen().block_connected(..)")]),t._v(" and/or "),s("code",[t._v("channel_monitor.block_connected(..)")]),t._v(".")]),t._v(" "),s("li",[t._v("Call "),s("code",[t._v("channel_manager.chain_sync_completed(..)")]),t._v(" to complete the initial sync process.")])]),t._v(" "),s("p",[s("strong",[t._v("Electrum/Esplora")])]),t._v(" "),s("p",[t._v("Alternatively, you can use LDK's "),s("code",[t._v("lightning-transaction-sync")]),t._v(" crate. This provides utilities for syncing LDK via the transaction-based "),s("code",[t._v("Confirm")]),t._v(" interface.")]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-p2pgossipsync-or-rapidgossipsync"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-p2pgossipsync-or-rapidgossipsync"}},[t._v("#")]),t._v(" Optional: Initialize "),s("code",[t._v("P2PGossipSync or RapidGossipSync")])]),t._v(" "),s("p",[s("strong",[t._v("You must follow this step if:")]),t._v(" you need LDK to provide routes for sending payments (i.e. you are "),s("em",[t._v("not")]),t._v(" providing your own routes)")]),t._v(" "),s("p",[s("strong",[t._v("What it's used for:")]),t._v(" generating routes to send payments over")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" genesis "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("genesis_block")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("header"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/network_graph"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" genesis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" gossip_sync "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("dyn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("chain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Access")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Send")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Sync")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-java extra-class"},[s("pre",{pre:!0,attrs:{class:"language-java"}},[s("code",[t._v("val genesisBlock "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BestBlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_genesis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("LDKNetwork_Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval genesisBlockHash "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byteArrayToHex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("genesisBlock"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("block_hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nval serializedNetworkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read network graph bytes from file")]),t._v("\nval networkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("serializedNetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nval p2pGossip "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("P2PGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option_AccessZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("none")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Network Graph exists, then read from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedNetworkGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read Network Graph bytes from file")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" readResult "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedNetworkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" arg"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" readResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" readResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Network Graph does not exist, create a new one")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" netGraph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NetworkGraph")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Initialise RGS")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rgs "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RapidGossipSync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lastSync "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getLastRapidGossipSyncTimestamp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" snapshot "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" lastSync"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateNetworkGraphNoStd")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("updateData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" snapshot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" currentTimeUnix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"RGS updated"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" snapshot "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use lastSyncTimeStamp as 0 for first Sync")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" rgs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("updateNetworkGraphNoStd")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("updateData"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" snapshot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" currentTimeUnix"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"RGS initialized for the first time"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get current snapshot from the RGS Server")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getSnapshot")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lastSyncTimeStamp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use LDK's RGS Server or use your own Server")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("URL")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("string"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https://rapidsync.lightningdevkit.org/snapshot/')]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v("\\(")]),s("span",{pre:!0,attrs:{class:"token interpolation"}},[t._v("lastSyncTimeStamp")]),s("span",{pre:!0,attrs:{class:"token interpolation-punctuation punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the url to get the data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" data "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Implementation notes:")]),t._v(" this struct is not required if you are providing your own routes. It will be used internally in "),s("code",[t._v("ChannelManager")]),t._v(" to build a "),s("code",[t._v("NetworkGraph")]),t._v(". Network options include: "),s("code",[t._v("Mainnet")]),t._v(","),s("code",[t._v("Regtest")]),t._v(","),s("code",[t._v("Testnet")]),t._v(","),s("code",[t._v("Signet")])]),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("Logger")])]),t._v(" "),s("p",[s("strong",[t._v("Optional dependency:")]),t._v(" "),s("code",[t._v("Access")]),t._v(", a source of chain information. Recommended to be able to verify channels before adding them to the internal network graph.")]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/gossip/struct.P2PGossipSync.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("P2PGossipSync")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Access.html",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("Access")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/P2PGossipSync.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("P2PGossipSync")]),t._v(" bindings"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://docs.rs/lightning-rapid-gossip-sync/*/lightning_rapid_gossip_sync/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("RapidGossipSync")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/RapidGossipSync.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("RapidGossipSync")]),t._v(" bindings"),s("OutboundLink")],1)]),t._v(" "),s("h3",{attrs:{id:"optional-initialize-probabilistic-scorer"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#optional-initialize-probabilistic-scorer"}},[t._v("#")]),t._v(" Optional: Initialize "),s("code",[t._v("Probabilistic Scorer")])]),t._v(" "),s("p",[s("strong",[t._v("What it's used for")]),t._v(": to find a suitable payment path to reach the destination.")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/network_graph"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" network_graph "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer_path "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("format!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{}/scorer"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ldk_data_dir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RwLock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("disk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_scorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Path")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("scorer_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("network_graph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerFile"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("exists")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" scorerReaderResult "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerFile"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("readBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerReaderResult"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("is_ok"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("scorerReaderResult "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_ProbabilisticScorerDecodeErrorZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_ProbabilisticScorerDecodeErrorZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Probabilistic Scorer loaded and running"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Couldn\'t load Probabilistic Scorer"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Log"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("i")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("LDKTAG"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"LDK: Creating a new Probabilistic Scorer"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScoringDecayParameters"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("with_default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" MultiThreadedLockableScore"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_Score")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-Swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Scorer exists, then read from disk")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Read Scorer bytes from file")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringDecayParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" serializedProbabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n ser"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" serializedScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argA"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argB"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n argC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" serializedProbabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" score "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Scorer loaded")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MultiThreadedLockableScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// If Scorer does not exist, create a new one")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" decayParams "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScoringDecayParameters")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithDefault")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" probabilisticScorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ProbabilisticScorer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" decayParams"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n networkGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" netGraph"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n logger"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" logger\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" score "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" probabilisticScorer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Scorer loaded")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" scorer "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MultiThreadedLockableScore")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" score"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("p",[s("strong",[t._v("Dependencies:")]),t._v(" "),s("code",[t._v("NetworkGraph")])]),t._v(" "),s("p",[s("strong",[t._v("References:")]),t._v(" "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/routing/scoring/struct.ProbabilisticScorer.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),s("code",[t._v("ProbabilisticScorer")]),t._v(" docs"),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/ProbabilisticScorer.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),s("code",[t._v("ProbabilisticScorer")]),t._v(" docs"),s("OutboundLink")],1)])],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/51.a32cb043.js b/assets/js/52.70176f22.js similarity index 99% rename from assets/js/51.a32cb043.js rename to assets/js/52.70176f22.js index 3372a69ba..c5fbd8533 100644 --- a/assets/js/51.a32cb043.js +++ b/assets/js/52.70176f22.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{412:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"setting-up-a-peermanager"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-a-peermanager"}},[t._v("#")]),t._v(" Setting up a "),a("code",[t._v("PeerManager")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("PeerManager")]),t._v(" is responsible for managing a set of peer connections and data associated with those peers.")]),t._v(" "),a("h2",{attrs:{id:"adding-a-peermanager"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#adding-a-peermanager"}},[t._v("#")]),t._v(" Adding a "),a("code",[t._v("PeerManager")])]),t._v(" "),a("p",[t._v("To add a "),a("code",[t._v("PeerManager")]),t._v(" to your application, run:")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("peer_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" ephemeral_bytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rand"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("thread_rng")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fill_bytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" ephemeral_bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lightning_msg_handler "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MessageHandler")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chan_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n route_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" gossip_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n onion_message_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onion_messenger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n custom_message_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IgnoringMessageHandler")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peer_manager "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n lightning_msg_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n cur_time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("try_into")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("log_error!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to get current time: {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildError")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvalidSystemTime")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ephemeral_bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("org"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v("\n\nval peerManager"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peer_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peerManager\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("Implementation notes:")]),t._v(" if you did not initialize "),a("code",[t._v("P2PGossipSync")]),t._v(" in the previous step, you can initialize your own struct (which can be a dummy struct) that implements "),a("code",[t._v("RoutingMessageHandler")])]),t._v(" "),a("p",[a("strong",[t._v("Dependencies:")]),t._v(" "),a("code",[t._v("ChannelManager")]),t._v(", "),a("code",[t._v("RoutingMessageHandler")]),t._v(", "),a("code",[t._v("KeysManager")]),t._v(", random bytes, "),a("code",[t._v("Logger")])]),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PeerManager")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/msgs/trait.RoutingMessageHandler.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("RoutingMessageHandler")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PeerManager")]),t._v(" bindings"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/RoutingMessageHandler.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("RoutingMessageHandler")]),t._v(" bindings"),a("OutboundLink")],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{416:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"setting-up-a-peermanager"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-a-peermanager"}},[t._v("#")]),t._v(" Setting up a "),a("code",[t._v("PeerManager")])]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("PeerManager")]),t._v(" is responsible for managing a set of peer connections and data associated with those peers.")]),t._v(" "),a("h2",{attrs:{id:"adding-a-peermanager"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#adding-a-peermanager"}},[t._v("#")]),t._v(" Adding a "),a("code",[t._v("PeerManager")])]),t._v(" "),a("p",[t._v("To add a "),a("code",[t._v("PeerManager")]),t._v(" to your application, run:")]),t._v(" "),a("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[a("div",{staticClass:"language-rust extra-class"},[a("pre",{pre:!0,attrs:{class:"language-rust"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("ln"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("peer_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" ephemeral_bytes "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rand"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("thread_rng")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fill_bytes")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" ephemeral_bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" lightning_msg_handler "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MessageHandler")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chan_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channel_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n route_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" gossip_sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n onion_message_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onion_messenger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n custom_message_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("IgnoringMessageHandler")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peer_manager "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n lightning_msg_handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n cur_time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("try_into")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token closure-params"}},[a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("log_error!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to get current time: {}"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildError")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InvalidSystemTime")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ephemeral_bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("logger"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("keys_manager\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[a("div",{staticClass:"language-java extra-class"},[a("pre",{pre:!0,attrs:{class:"language-java"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("org"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldk"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("structs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")])]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v("\n\nval peerManager"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peer_manager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[a("div",{staticClass:"language-Swift extra-class"},[a("pre",{pre:!0,attrs:{class:"language-swift"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("LightningDevKit")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" peerManager"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PeerManager")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" channelManagerConstructor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("peerManager\n")])])])]},proxy:!0}])}),t._v(" "),a("p",[a("strong",[t._v("Implementation notes:")]),t._v(" if you did not initialize "),a("code",[t._v("P2PGossipSync")]),t._v(" in the previous step, you can initialize your own struct (which can be a dummy struct) that implements "),a("code",[t._v("RoutingMessageHandler")])]),t._v(" "),a("p",[a("strong",[t._v("Dependencies:")]),t._v(" "),a("code",[t._v("ChannelManager")]),t._v(", "),a("code",[t._v("RoutingMessageHandler")]),t._v(", "),a("code",[t._v("KeysManager")]),t._v(", random bytes, "),a("code",[t._v("Logger")])]),t._v(" "),a("p",[a("strong",[t._v("References:")]),t._v(" "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/peer_handler/struct.PeerManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("PeerManager")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/ln/msgs/trait.RoutingMessageHandler.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust "),a("code",[t._v("RoutingMessageHandler")]),t._v(" docs"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/PeerManager.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("PeerManager")]),t._v(" bindings"),a("OutboundLink")],1),t._v(", "),a("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/RoutingMessageHandler.java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Java/Kotlin "),a("code",[t._v("RoutingMessageHandler")]),t._v(" bindings"),a("OutboundLink")],1)])],1)}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/52.1b223606.js b/assets/js/53.b24ea71d.js similarity index 99% rename from assets/js/52.1b223606.js rename to assets/js/53.b24ea71d.js index 748b64077..78e996f04 100644 --- a/assets/js/52.1b223606.js +++ b/assets/js/53.b24ea71d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{414:function(e,t,i){"use strict";i.r(t);var o=i(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"ldk-code-of-conduct"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-code-of-conduct"}},[e._v("#")]),e._v(" LDK Code of Conduct")]),e._v(" "),t("p",[e._v("The LDK community is open to pretty much anyone. To ensure that project forums such as the Discord server and GitHub repository are open and friendly, we count on maintainers and project representatives to behave in a way that is not disruptive to LDK's culture or to any one participant's well-being.")]),e._v(" "),t("p",[e._v("Therefore, we came up with some easy to follow guidelines.")]),e._v(" "),t("ul",[t("li",[e._v("Be friendly. Interact in a way that fosters openness, inclusivity, and collaboration.")]),e._v(" "),t("li",[e._v("Be respectful. We may disagree, but disagreement is no excuse for rude behavior or personal attacks.")]),e._v(" "),t("li",[e._v("Be considerate. Provide and accept constructive criticism.")])]),e._v(" "),t("p",[e._v("Private or public harassment of any kind will not be tolerated. Since harassment can take many forms, here's a non-exhaustive list of what we consider unacceptable behavior:")]),e._v(" "),t("ul",[t("li",[e._v("Offensive language directed at individuals or groups of people")]),e._v(" "),t("li",[e._v("Bullying (verbal, physical, social, or cyber)")]),e._v(" "),t("li",[e._v("Interfering with someone's ability to contribute, like with excessive nitpicking")]),e._v(" "),t("li",[e._v("Continued one-on-one communication after a party has requested it cease")]),e._v(" "),t("li",[e._v("Stalking online or offline")]),e._v(" "),t("li",[e._v("Doxing or unauthorized publication of private information or communication")]),e._v(" "),t("li",[e._v("Unwelcomed sexual attention")]),e._v(" "),t("li",[e._v("Inappropriate visual displays such as sexually-oriented or offensive photography, cartoons, drawings, or gestures")]),e._v(" "),t("li",[e._v("Retaliation for reporting or threatening to report harassment")])]),e._v(" "),t("p",[e._v("Additionally, spam and other content which disrupts or prevents LDK contributors from working on LDK is not acceptable.")]),e._v(" "),t("h2",{attrs:{id:"the-code-of-conduct-team"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-code-of-conduct-team"}},[e._v("#")]),e._v(" The Code of Conduct Team")]),e._v(" "),t("p",[e._v("A small team of LDK contributors has volunteered to enforce the LDK Code of Conduct. If you feel like a community member has engaged in inappropriate behavior, please don't hesitate to contact one of the following LDK contributors via email or on Discord:")]),e._v(" "),t("ul",[t("li",[e._v("Matt Corallo - ldkcocpoc on mattcorallo.com")]),e._v(" "),t("li",[e._v("Val Wallace - vwallace on protonmail.com")]),e._v(" "),t("li",[e._v("Devrandom - devrandom99 on proton.me")])]),e._v(" "),t("h2",{attrs:{id:"the-code-of-conduct-team-s-responsibilities"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-code-of-conduct-team-s-responsibilities"}},[e._v("#")]),e._v(" The Code of Conduct Team’s Responsibilities")]),e._v(" "),t("p",[e._v("Team members are tasked with responding to reports within 24 hours. They will review each incident and determine, to the best of their ability:")]),e._v(" "),t("ul",[t("li",[e._v("Does the event constitute a Code of Conduct violation?")]),e._v(" "),t("li",[e._v("Is the behavior on our list of inappropriate behavior? Is it borderline inappropriate?")]),e._v(" "),t("li",[e._v("Did the event occur in a space within our Code of Conduct's scope?\n"),t("ul",[t("li",[e._v("If the incident occurred outside community forums and the individual is seen as a project representative or identifies as an LDK contributor, the incident may be in scope.")]),e._v(" "),t("li",[e._v("Additionally, an incident may be in scope if a community member's ability to contribute to LDK is impacted.")])])]),e._v(" "),t("li",[e._v("Did this incident occur in a private conversation or in a public space?")]),e._v(" "),t("li",[e._v("Is the situation isolated or ongoing?")]),e._v(" "),t("li",[e._v("How is the reported person's behavior negatively impacting others?")]),e._v(" "),t("li",[e._v("Does the incident impact the ability of individuals to freely contribute to LDK?")]),e._v(" "),t("li",[e._v("Does this incident include sexual harassment?")]),e._v(" "),t("li",[e._v("Does this pose a safety risk or severely negatively impact someone's mental health?")]),e._v(" "),t("li",[e._v("Is there a risk of this behavior being repeated?")]),e._v(" "),t("li",[e._v("Does the reported person understand why their behavior was inappropriate?")])]),e._v(" "),t("p",[e._v("If a report is insufficiently detailed or involves multiple parties, the Code of Conduct Team may seek additional information from witnesses or the accused. Neither party should contact the other to discuss the incident. Likewise, the team will do its best not to disclose who reported a given incident, either to the accused or generally, though we recognize that circumstantial disclosures to the accused might be unavoidable.")]),e._v(" "),t("p",[e._v("The Code of Conduct Team aims to resolve all reports within one week. If a resolution is not possible within that time frame, the team will respond to the reporter(s) with an adjusted one.")]),e._v(" "),t("h2",{attrs:{id:"possible-responses-to-an-incident-include"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#possible-responses-to-an-incident-include"}},[e._v("#")]),e._v(" Possible responses to an incident include:")]),e._v(" "),t("h3",{attrs:{id:"taking-no-further-action"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#taking-no-further-action"}},[e._v("#")]),e._v(" Taking no further action:")]),e._v(" "),t("p",[e._v("If the Code of Conduct Team determines that no action is needed, they will inform the reporter.")]),e._v(" "),t("h3",{attrs:{id:"simple-warning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#simple-warning"}},[e._v("#")]),e._v(" Simple warning:")]),e._v(" "),t("p",[e._v("This applies to disruptive behavior, but not insulting behavior. The Code of Conduct Team will contact the individual(s) and request that they stop.")]),e._v(" "),t("h3",{attrs:{id:"final-warning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#final-warning"}},[e._v("#")]),e._v(" Final warning:")]),e._v(" "),t("p",[e._v("If an incident or series of incidents creates sustained toxicity within the LDK Community, the Code of Conduct Team will sternly warn the reported party and raise the possibility of further disciplinary action. In addition, they may request that the reported party:")]),e._v(" "),t("ul",[t("li",[e._v("Not use specific language")]),e._v(" "),t("li",[e._v("Not participate in specific types of discussions")]),e._v(" "),t("li",[e._v("Not send private messages to a community member")]),e._v(" "),t("li",[e._v("Not review a particular person's PRs on GitHub (but still allow them to privately share review comments with a maintainer)")]),e._v(" "),t("li",[e._v("Not lead sub-projects like code review sessions")]),e._v(" "),t("li",[e._v("Take a step away for a short period to cool off")]),e._v(" "),t("li",[e._v("Lose maintainer/merge access")])]),e._v(" "),t("h3",{attrs:{id:"2-3-months-imposed-break"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#2-3-months-imposed-break"}},[e._v("#")]),e._v(" 2-3 months imposed break:")]),e._v(" "),t("p",[e._v("If the Code of Conduct Team’s warning goes unheeded, the individual(s) may be asked to avoid participating with the LDK Community on its preferred platforms for several months. After time has passed, the individual(s) will have the option of meeting with the team to discuss returning to the community.")]),e._v(" "),t("h3",{attrs:{id:"extended-or-permanent-ban"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#extended-or-permanent-ban"}},[e._v("#")]),e._v(" Extended or permanent ban:")]),e._v(" "),t("p",[e._v("If a temporary break does not remedy a serious offense, the offender may be removed from the Discord server and Github repository. The Code of Conduct Team may also choose to un-ban a user for a first offense, depending on its severity and pending that the user has offered the offended party a genuine apology.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{423:function(e,t,i){"use strict";i.r(t);var o=i(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"ldk-code-of-conduct"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-code-of-conduct"}},[e._v("#")]),e._v(" LDK Code of Conduct")]),e._v(" "),t("p",[e._v("The LDK community is open to pretty much anyone. To ensure that project forums such as the Discord server and GitHub repository are open and friendly, we count on maintainers and project representatives to behave in a way that is not disruptive to LDK's culture or to any one participant's well-being.")]),e._v(" "),t("p",[e._v("Therefore, we came up with some easy to follow guidelines.")]),e._v(" "),t("ul",[t("li",[e._v("Be friendly. Interact in a way that fosters openness, inclusivity, and collaboration.")]),e._v(" "),t("li",[e._v("Be respectful. We may disagree, but disagreement is no excuse for rude behavior or personal attacks.")]),e._v(" "),t("li",[e._v("Be considerate. Provide and accept constructive criticism.")])]),e._v(" "),t("p",[e._v("Private or public harassment of any kind will not be tolerated. Since harassment can take many forms, here's a non-exhaustive list of what we consider unacceptable behavior:")]),e._v(" "),t("ul",[t("li",[e._v("Offensive language directed at individuals or groups of people")]),e._v(" "),t("li",[e._v("Bullying (verbal, physical, social, or cyber)")]),e._v(" "),t("li",[e._v("Interfering with someone's ability to contribute, like with excessive nitpicking")]),e._v(" "),t("li",[e._v("Continued one-on-one communication after a party has requested it cease")]),e._v(" "),t("li",[e._v("Stalking online or offline")]),e._v(" "),t("li",[e._v("Doxing or unauthorized publication of private information or communication")]),e._v(" "),t("li",[e._v("Unwelcomed sexual attention")]),e._v(" "),t("li",[e._v("Inappropriate visual displays such as sexually-oriented or offensive photography, cartoons, drawings, or gestures")]),e._v(" "),t("li",[e._v("Retaliation for reporting or threatening to report harassment")])]),e._v(" "),t("p",[e._v("Additionally, spam and other content which disrupts or prevents LDK contributors from working on LDK is not acceptable.")]),e._v(" "),t("h2",{attrs:{id:"the-code-of-conduct-team"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-code-of-conduct-team"}},[e._v("#")]),e._v(" The Code of Conduct Team")]),e._v(" "),t("p",[e._v("A small team of LDK contributors has volunteered to enforce the LDK Code of Conduct. If you feel like a community member has engaged in inappropriate behavior, please don't hesitate to contact one of the following LDK contributors via email or on Discord:")]),e._v(" "),t("ul",[t("li",[e._v("Matt Corallo - ldkcocpoc on mattcorallo.com")]),e._v(" "),t("li",[e._v("Val Wallace - vwallace on protonmail.com")]),e._v(" "),t("li",[e._v("Devrandom - devrandom99 on proton.me")])]),e._v(" "),t("h2",{attrs:{id:"the-code-of-conduct-team-s-responsibilities"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-code-of-conduct-team-s-responsibilities"}},[e._v("#")]),e._v(" The Code of Conduct Team’s Responsibilities")]),e._v(" "),t("p",[e._v("Team members are tasked with responding to reports within 24 hours. They will review each incident and determine, to the best of their ability:")]),e._v(" "),t("ul",[t("li",[e._v("Does the event constitute a Code of Conduct violation?")]),e._v(" "),t("li",[e._v("Is the behavior on our list of inappropriate behavior? Is it borderline inappropriate?")]),e._v(" "),t("li",[e._v("Did the event occur in a space within our Code of Conduct's scope?\n"),t("ul",[t("li",[e._v("If the incident occurred outside community forums and the individual is seen as a project representative or identifies as an LDK contributor, the incident may be in scope.")]),e._v(" "),t("li",[e._v("Additionally, an incident may be in scope if a community member's ability to contribute to LDK is impacted.")])])]),e._v(" "),t("li",[e._v("Did this incident occur in a private conversation or in a public space?")]),e._v(" "),t("li",[e._v("Is the situation isolated or ongoing?")]),e._v(" "),t("li",[e._v("How is the reported person's behavior negatively impacting others?")]),e._v(" "),t("li",[e._v("Does the incident impact the ability of individuals to freely contribute to LDK?")]),e._v(" "),t("li",[e._v("Does this incident include sexual harassment?")]),e._v(" "),t("li",[e._v("Does this pose a safety risk or severely negatively impact someone's mental health?")]),e._v(" "),t("li",[e._v("Is there a risk of this behavior being repeated?")]),e._v(" "),t("li",[e._v("Does the reported person understand why their behavior was inappropriate?")])]),e._v(" "),t("p",[e._v("If a report is insufficiently detailed or involves multiple parties, the Code of Conduct Team may seek additional information from witnesses or the accused. Neither party should contact the other to discuss the incident. Likewise, the team will do its best not to disclose who reported a given incident, either to the accused or generally, though we recognize that circumstantial disclosures to the accused might be unavoidable.")]),e._v(" "),t("p",[e._v("The Code of Conduct Team aims to resolve all reports within one week. If a resolution is not possible within that time frame, the team will respond to the reporter(s) with an adjusted one.")]),e._v(" "),t("h2",{attrs:{id:"possible-responses-to-an-incident-include"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#possible-responses-to-an-incident-include"}},[e._v("#")]),e._v(" Possible responses to an incident include:")]),e._v(" "),t("h3",{attrs:{id:"taking-no-further-action"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#taking-no-further-action"}},[e._v("#")]),e._v(" Taking no further action:")]),e._v(" "),t("p",[e._v("If the Code of Conduct Team determines that no action is needed, they will inform the reporter.")]),e._v(" "),t("h3",{attrs:{id:"simple-warning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#simple-warning"}},[e._v("#")]),e._v(" Simple warning:")]),e._v(" "),t("p",[e._v("This applies to disruptive behavior, but not insulting behavior. The Code of Conduct Team will contact the individual(s) and request that they stop.")]),e._v(" "),t("h3",{attrs:{id:"final-warning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#final-warning"}},[e._v("#")]),e._v(" Final warning:")]),e._v(" "),t("p",[e._v("If an incident or series of incidents creates sustained toxicity within the LDK Community, the Code of Conduct Team will sternly warn the reported party and raise the possibility of further disciplinary action. In addition, they may request that the reported party:")]),e._v(" "),t("ul",[t("li",[e._v("Not use specific language")]),e._v(" "),t("li",[e._v("Not participate in specific types of discussions")]),e._v(" "),t("li",[e._v("Not send private messages to a community member")]),e._v(" "),t("li",[e._v("Not review a particular person's PRs on GitHub (but still allow them to privately share review comments with a maintainer)")]),e._v(" "),t("li",[e._v("Not lead sub-projects like code review sessions")]),e._v(" "),t("li",[e._v("Take a step away for a short period to cool off")]),e._v(" "),t("li",[e._v("Lose maintainer/merge access")])]),e._v(" "),t("h3",{attrs:{id:"2-3-months-imposed-break"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#2-3-months-imposed-break"}},[e._v("#")]),e._v(" 2-3 months imposed break:")]),e._v(" "),t("p",[e._v("If the Code of Conduct Team’s warning goes unheeded, the individual(s) may be asked to avoid participating with the LDK Community on its preferred platforms for several months. After time has passed, the individual(s) will have the option of meeting with the team to discuss returning to the community.")]),e._v(" "),t("h3",{attrs:{id:"extended-or-permanent-ban"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#extended-or-permanent-ban"}},[e._v("#")]),e._v(" Extended or permanent ban:")]),e._v(" "),t("p",[e._v("If a temporary break does not remedy a serious offense, the offender may be removed from the Discord server and Github repository. The Code of Conduct Team may also choose to un-ban a user for a first offense, depending on its severity and pending that the user has offered the offended party a genuine apology.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/53.6d4715fe.js b/assets/js/54.0fafc6dd.js similarity index 99% rename from assets/js/53.6d4715fe.js rename to assets/js/54.0fafc6dd.js index 34997b1ea..e05ec5e39 100644 --- a/assets/js/53.6d4715fe.js +++ b/assets/js/54.0fafc6dd.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{415:function(e,t,a){"use strict";a.r(t);var r=a(7),n=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"examples"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),t("p",[e._v("Click the links below and learn from community-built example projects")]),e._v(" "),t("h3",{attrs:{id:"rust-sample-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-sample-node"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust Sample Node"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample serves as a complete reference for constructing a lightning node with\nLDK. This is a good starting point if you want a self-guided tour.")]),e._v(" "),t("h3",{attrs:{id:"kotlinandroid-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#kotlinandroid-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/conorokus/umlando-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kotlin/Android Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses the Kotlin bindings provided by "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-garbagecollected"),t("OutboundLink")],1),e._v(" to create a self-custodial mobile lightning wallet on Android.")]),e._v(" "),t("h3",{attrs:{id:"swiftios-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#swiftios-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/Roy0Anonymous/Vajra-Wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Swift/iOS Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses the Swift bindings provided by "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-swift",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-swift"),t("OutboundLink")],1),e._v(" to create a self-custodial mobile lightning wallet on iOS.")]),e._v(" "),t("h3",{attrs:{id:"rust-node-with-sample-lightning-signer-integration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-node-with-sample-lightning-signer-integration"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://gitlab.com/lightning-signer/lnrod/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust node with sample Lightning Signer integration"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A Rust lightning node implementation based on LDK and the Lightning Signer projects. Aims to be production ready at some point.")]),e._v(" "),t("h3",{attrs:{id:"rust-node-with-sample-tor-integration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-node-with-sample-tor-integration"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/TonyGiorgio/ldk-sample-tor",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust node with sample Tor integration"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A Rust lightning node sample implementation based on LDK with an embedded Tor daemon.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A ready-to-go Lightning node library built using LDK and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-rust-sample"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-rust-sample"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/optout21/ldk-node-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Rust Sample"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A sample lightning node command-line app built on top of LDK Node (similar to ldk-sample).")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-swift-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-swift-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/reez/Monday/tree/main/LDKNodeMonday",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Swift Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node/blob/main/Package.swift",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-node-swift"),t("OutboundLink")],1),e._v(" bindings to quickly build a self custodial lightning mobile wallet on iOS. Watch the video tutorial "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=rcU3LU6iZCs",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-swift-sample-app-using-bitcoin-design-guide"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-swift-sample-app-using-bitcoin-design-guide"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/bdgwallet/dailywallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Swift Sample app using Bitcoin Design Guide"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a good starting point for building a sample iOS wallet with a strong focus on user experience.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-flutter-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-flutter-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-flutter-demo",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Flutter Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a starting point for an LDK Node Flutter app.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-react-native-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-react-native-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-rn-demo",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node React Native Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a starting point for an LDK Node React Native app.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-sample-desktop-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-sample-desktop-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/jbesraa/ldk-node-desktop",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Sample Desktop App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a desktop node manager for LDK Node.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{419:function(e,t,a){"use strict";a.r(t);var r=a(7),n=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"examples"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#examples"}},[e._v("#")]),e._v(" Examples")]),e._v(" "),t("p",[e._v("Click the links below and learn from community-built example projects")]),e._v(" "),t("h3",{attrs:{id:"rust-sample-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-sample-node"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust Sample Node"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample serves as a complete reference for constructing a lightning node with\nLDK. This is a good starting point if you want a self-guided tour.")]),e._v(" "),t("h3",{attrs:{id:"kotlinandroid-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#kotlinandroid-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/conorokus/umlando-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kotlin/Android Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses the Kotlin bindings provided by "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-garbagecollected",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-garbagecollected"),t("OutboundLink")],1),e._v(" to create a self-custodial mobile lightning wallet on Android.")]),e._v(" "),t("h3",{attrs:{id:"swiftios-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#swiftios-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/Roy0Anonymous/Vajra-Wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Swift/iOS Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses the Swift bindings provided by "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-swift",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-swift"),t("OutboundLink")],1),e._v(" to create a self-custodial mobile lightning wallet on iOS.")]),e._v(" "),t("h3",{attrs:{id:"rust-node-with-sample-lightning-signer-integration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-node-with-sample-lightning-signer-integration"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://gitlab.com/lightning-signer/lnrod/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust node with sample Lightning Signer integration"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A Rust lightning node implementation based on LDK and the Lightning Signer projects. Aims to be production ready at some point.")]),e._v(" "),t("h3",{attrs:{id:"rust-node-with-sample-tor-integration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rust-node-with-sample-tor-integration"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/TonyGiorgio/ldk-sample-tor",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rust node with sample Tor integration"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A Rust lightning node sample implementation based on LDK with an embedded Tor daemon.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A ready-to-go Lightning node library built using LDK and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-rust-sample"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-rust-sample"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/optout21/ldk-node-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Rust Sample"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("A sample lightning node command-line app built on top of LDK Node (similar to ldk-sample).")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-swift-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-swift-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/reez/Monday/tree/main/LDKNodeMonday",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Swift Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample uses "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-node/blob/main/Package.swift",target:"_blank",rel:"noopener noreferrer"}},[e._v("ldk-node-swift"),t("OutboundLink")],1),e._v(" bindings to quickly build a self custodial lightning mobile wallet on iOS. Watch the video tutorial "),t("a",{attrs:{href:"https://www.youtube.com/watch?v=rcU3LU6iZCs",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-swift-sample-app-using-bitcoin-design-guide"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-swift-sample-app-using-bitcoin-design-guide"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/bdgwallet/dailywallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Swift Sample app using Bitcoin Design Guide"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a good starting point for building a sample iOS wallet with a strong focus on user experience.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-flutter-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-flutter-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-flutter-demo",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Flutter Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a starting point for an LDK Node Flutter app.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-react-native-sample-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-react-native-sample-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/LtbLightning/ldk-node-rn-demo",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node React Native Sample App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a starting point for an LDK Node React Native app.")]),e._v(" "),t("h3",{attrs:{id:"ldk-node-sample-desktop-app"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ldk-node-sample-desktop-app"}},[e._v("#")]),e._v(" "),t("a",{attrs:{href:"https://github.com/jbesraa/ldk-node-desktop",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK Node Sample Desktop App"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("This sample is a desktop node manager for LDK Node.")])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/54.e932f92d.js b/assets/js/55.f6576e42.js similarity index 94% rename from assets/js/54.e932f92d.js rename to assets/js/55.f6576e42.js index 664c9bc72..05d565e3f 100644 --- a/assets/js/54.e932f92d.js +++ b/assets/js/55.f6576e42.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{417:function(t,n,e){"use strict";e.r(n);var o=e(7),a=Object(o.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"blockchain-data"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#blockchain-data"}},[t._v("#")]),t._v(" Blockchain Data")]),t._v(" "),n("p",[t._v("LDK provides a simple "),n("code",[t._v("block_connected")]),t._v("/"),n("code",[t._v("block_disconnected")]),t._v(" API which you pass block headers and transaction information to. LDK also provides an API for getting information about transactions it wishes to be informed of, which is compatible with Electrum server requests/neutrino filtering/etc.")]),t._v(" "),n("p",[n("a",{attrs:{href:"https://lightningdevkit.org/blockchain_data/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Blockchain Data Guide"),n("OutboundLink")],1)]),t._v(" "),n("p",[n("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-lightning/tree/main/lightning-block-sync",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample module in Rust"),n("OutboundLink")],1)])])}),[],!1,null,null,null);n.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[55],{421:function(t,n,e){"use strict";e.r(n);var o=e(7),a=Object(o.a)({},(function(){var t=this,n=t._self._c;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"blockchain-data"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#blockchain-data"}},[t._v("#")]),t._v(" Blockchain Data")]),t._v(" "),n("p",[t._v("LDK provides a simple "),n("code",[t._v("block_connected")]),t._v("/"),n("code",[t._v("block_disconnected")]),t._v(" API which you pass block headers and transaction information to. LDK also provides an API for getting information about transactions it wishes to be informed of, which is compatible with Electrum server requests/neutrino filtering/etc.")]),t._v(" "),n("p",[n("a",{attrs:{href:"https://lightningdevkit.org/blockchain_data/introduction/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Blockchain Data Guide"),n("OutboundLink")],1)]),t._v(" "),n("p",[n("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-lightning/tree/main/lightning-block-sync",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample module in Rust"),n("OutboundLink")],1)])])}),[],!1,null,null,null);n.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/55.b21eece9.js b/assets/js/56.d6c3718a.js similarity index 98% rename from assets/js/55.b21eece9.js rename to assets/js/56.d6c3718a.js index df72c7f87..e1e8c65d4 100644 --- a/assets/js/55.b21eece9.js +++ b/assets/js/56.d6c3718a.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[55],{419:function(t,e,n){"use strict";n.r(e);var a=n(7),o=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("Lightning Development Kit (LDK) is a full and completely standalone Lightning implementation with supporting modules enabling greater flexibility.")]),t._v(" "),e("p",[t._v("You can build a Lightning node without needing to worry about getting all of the Lightning state machine, routing, and on-chain punishment code (and other chain interactions) exactly correct. LDK tends to be suitable for use cases where a degree of customization is desired, e.g. your own chain sync, your own key management and/or your own storage/backup logic.")]),t._v(" "),e("p",[t._v("Our "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("sample node"),e("OutboundLink")],1),t._v(" showcases how LDK can be customised. It fetches blockchain data and transacts on-chain via Bitcoin Core RPC/REST. The individual components of the sample are composable. For example, the sample writes channel state to the local filesystem, but this component could be replaced with one that writes this data to the cloud or to multiple locations. You can pick the off-the-shelf parts you want and replace the rest.")]),t._v(" "),e("p",[t._v("To start building a node with LDK "),e("RouterLink",{attrs:{to:"/building-a-node-with-ldk/introduction/"}},[t._v("click here.")])],1),t._v(" "),e("h2",{attrs:{id:"references"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#references"}},[t._v("#")]),t._v(" References")]),t._v(" "),e("h3",{attrs:{id:"rust-documentation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rust-documentation"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://docs.rs/lightning",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Documentation"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("These provide the most searchable and comprehensive documentation on LDK.\nIf you're using Java and want more information on any method/struct/etc., searching\nthe Rust docs for the Rust version of that struct/method is your best bet.")]),t._v(" "),e("h3",{attrs:{id:"swift-ldk-documentation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#swift-ldk-documentation"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/arik-so/SwiftLightning/tree/master/Documentation",target:"_blank",rel:"noopener noreferrer"}},[t._v("Swift LDK Documentation"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("These docs are mainly geared towards how Swift could call LDK C bindings directly, but still may\nprovide a useful overview of Rust Lightning in the context of language bindings.")]),t._v(" "),e("h3",{attrs:{id:"rust-sample-node"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rust-sample-node"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Sample Node"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("The sample serves as a complete reference for constructing a Lightning node with\nthe LDK. This is a good starting point if you want a self-guided tour!")]),t._v(" "),e("h3",{attrs:{id:"architecture"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#architecture"}},[t._v("#")]),t._v(" "),e("RouterLink",{attrs:{to:"/introduction/architecture/"}},[t._v("Architecture")])],1),t._v(" "),e("p",[t._v("Gives a high-level organization of LDK and how the pieces fit together. Variations of this diagram\nare used throughout the site. This is the primary source and is still a work in progress.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[56],{424:function(t,e,n){"use strict";n.r(e);var a=n(7),o=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("Lightning Development Kit (LDK) is a full and completely standalone Lightning implementation with supporting modules enabling greater flexibility.")]),t._v(" "),e("p",[t._v("You can build a Lightning node without needing to worry about getting all of the Lightning state machine, routing, and on-chain punishment code (and other chain interactions) exactly correct. LDK tends to be suitable for use cases where a degree of customization is desired, e.g. your own chain sync, your own key management and/or your own storage/backup logic.")]),t._v(" "),e("p",[t._v("Our "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("sample node"),e("OutboundLink")],1),t._v(" showcases how LDK can be customised. It fetches blockchain data and transacts on-chain via Bitcoin Core RPC/REST. The individual components of the sample are composable. For example, the sample writes channel state to the local filesystem, but this component could be replaced with one that writes this data to the cloud or to multiple locations. You can pick the off-the-shelf parts you want and replace the rest.")]),t._v(" "),e("p",[t._v("To start building a node with LDK "),e("RouterLink",{attrs:{to:"/building-a-node-with-ldk/introduction/"}},[t._v("click here.")])],1),t._v(" "),e("h2",{attrs:{id:"references"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#references"}},[t._v("#")]),t._v(" References")]),t._v(" "),e("h3",{attrs:{id:"rust-documentation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rust-documentation"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://docs.rs/lightning",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Documentation"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("These provide the most searchable and comprehensive documentation on LDK.\nIf you're using Java and want more information on any method/struct/etc., searching\nthe Rust docs for the Rust version of that struct/method is your best bet.")]),t._v(" "),e("h3",{attrs:{id:"swift-ldk-documentation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#swift-ldk-documentation"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/arik-so/SwiftLightning/tree/master/Documentation",target:"_blank",rel:"noopener noreferrer"}},[t._v("Swift LDK Documentation"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("These docs are mainly geared towards how Swift could call LDK C bindings directly, but still may\nprovide a useful overview of Rust Lightning in the context of language bindings.")]),t._v(" "),e("h3",{attrs:{id:"rust-sample-node"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rust-sample-node"}},[t._v("#")]),t._v(" "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust Sample Node"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("The sample serves as a complete reference for constructing a Lightning node with\nthe LDK. This is a good starting point if you want a self-guided tour!")]),t._v(" "),e("h3",{attrs:{id:"architecture"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#architecture"}},[t._v("#")]),t._v(" "),e("RouterLink",{attrs:{to:"/introduction/architecture/"}},[t._v("Architecture")])],1),t._v(" "),e("p",[t._v("Gives a high-level organization of LDK and how the pieces fit together. Variations of this diagram\nare used throughout the site. This is the primary source and is still a work in progress.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/56.cfaddd05.js b/assets/js/57.99cf355c.js similarity index 93% rename from assets/js/56.cfaddd05.js rename to assets/js/57.99cf355c.js index 63a699ed1..9249dfd76 100644 --- a/assets/js/56.cfaddd05.js +++ b/assets/js/57.99cf355c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[56],{420:function(t,e,n){"use strict";n.r(e);var o=n(7),i=Object(o.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"networking"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#networking"}},[this._v("#")]),this._v(" Networking")]),this._v(" "),t("p",[this._v("To enable you to run a full Lightning node on an embedded machine, LDK doesn't specify exactly how to connect to another node at all! The default implementation uses TCP sockets, but, e.g., if you wanted to run your full Lightning node on a hardware wallet, you could, by piping the Lightning network messages over USB/serial and then sending them in a TCP socket from another machine.")]),this._v(" "),t("p",[this._v("Learn more about "),t("RouterLink",{attrs:{to:"/building-a-node-with-ldk/connect-to-peers/"}},[this._v("connect to peers.")])],1)])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[57],{425:function(t,e,n){"use strict";n.r(e);var o=n(7),i=Object(o.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"networking"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#networking"}},[this._v("#")]),this._v(" Networking")]),this._v(" "),t("p",[this._v("To enable you to run a full Lightning node on an embedded machine, LDK doesn't specify exactly how to connect to another node at all! The default implementation uses TCP sockets, but, e.g., if you wanted to run your full Lightning node on a hardware wallet, you could, by piping the Lightning network messages over USB/serial and then sending them in a TCP socket from another machine.")]),this._v(" "),t("p",[this._v("Learn more about "),t("RouterLink",{attrs:{to:"/building-a-node-with-ldk/connect-to-peers/"}},[this._v("connect to peers.")])],1)])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/57.b3ec8a0c.js b/assets/js/58.9c5fcaa8.js similarity index 94% rename from assets/js/57.b3ec8a0c.js rename to assets/js/58.9c5fcaa8.js index a6915fc37..9346bda77 100644 --- a/assets/js/57.b3ec8a0c.js +++ b/assets/js/58.9c5fcaa8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[57],{421:function(t,e,r){"use strict";r.r(e);var n=r(7),s=Object(n.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"persistent-storage"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#persistent-storage"}},[t._v("#")]),t._v(" Persistent Storage")]),t._v(" "),e("p",[t._v("You can store the channel state any way you want - whether Google Drive/iCloud, a local disk, any key-value store/database/a remote server, or any combination of them - LDK provides a clean API, where objects can be serialized into simple binary blobs, and stored in any way you wish.")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("Persist")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-lightning/tree/main/lightning-persister",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample module in Rust"),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[58],{426:function(t,e,r){"use strict";r.r(e);var n=r(7),s=Object(n.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"persistent-storage"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#persistent-storage"}},[t._v("#")]),t._v(" Persistent Storage")]),t._v(" "),e("p",[t._v("You can store the channel state any way you want - whether Google Drive/iCloud, a local disk, any key-value store/database/a remote server, or any combination of them - LDK provides a clean API, where objects can be serialized into simple binary blobs, and stored in any way you wish.")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/latest/lightning/chain/chainmonitor/trait.Persist.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("Persist")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-lightning/tree/main/lightning-persister",target:"_blank",rel:"noopener noreferrer"}},[t._v("Sample module in Rust"),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/58.2300774c.js b/assets/js/59.83c58e2d.js similarity index 94% rename from assets/js/58.2300774c.js rename to assets/js/59.83c58e2d.js index 99ac12871..5ce03a8eb 100644 --- a/assets/js/58.2300774c.js +++ b/assets/js/59.83c58e2d.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[58],{423:function(e,t,n){"use strict";n.r(t);var a=n(7),r=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"private-key-management"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#private-key-management"}},[e._v("#")]),e._v(" Private Key Management")]),e._v(" "),t("p",[e._v("LDK provides a default implementation for key management, but you can choose to provide private keys to LDK in any way you wish following a simple API. LDK even supports a generic API for signing transactions, allowing you to run LDK without any private keys in memory and/or putting private keys only on hardware wallets.")]),e._v(" "),t("p",[e._v("While LDK's default implementation is currently located within the "),t("code",[e._v("rust-lightning")]),e._v(" crate, it is still considered a sample module.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK's "),t("code",[e._v("KeysManager")]),e._v(" docs"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[59],{428:function(e,t,n){"use strict";n.r(t);var a=n(7),r=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"private-key-management"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#private-key-management"}},[e._v("#")]),e._v(" Private Key Management")]),e._v(" "),t("p",[e._v("LDK provides a default implementation for key management, but you can choose to provide private keys to LDK in any way you wish following a simple API. LDK even supports a generic API for signing transactions, allowing you to run LDK without any private keys in memory and/or putting private keys only on hardware wallets.")]),e._v(" "),t("p",[e._v("While LDK's default implementation is currently located within the "),t("code",[e._v("rust-lightning")]),e._v(" crate, it is still considered a sample module.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("LDK's "),t("code",[e._v("KeysManager")]),e._v(" docs"),t("OutboundLink")],1),e._v(".")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/6.72813d4f.js b/assets/js/6.a660e99e.js similarity index 98% rename from assets/js/6.72813d4f.js rename to assets/js/6.a660e99e.js index dffc7056a..f32f6e4f6 100644 --- a/assets/js/6.72813d4f.js +++ b/assets/js/6.a660e99e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6,8],{251:function(t,e){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},254:function(t,e,n){},255:function(t,e,n){},256:function(t,e,n){},257:function(t,e,n){},258:function(t,e,n){"use strict";n(254)},260:function(t,e,n){"use strict";var r={name:"PostMeta",props:["post"],filters:{capitalize:n(251).capitalize}},i=(n(258),n(7)),s=Object(i.a)(r,(function(){var t=this,e=t._self._c;return e("p",{staticClass:"meta"},[t._v("\n By\n\n "),t._l(t.post.frontmatter.authors,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/author/"+n}},[t._v(t._s(n))]),r!=t.post.frontmatter.authors.length-1?e("span",[t._v(", ")]):t._e()],1)})),t._v("\n\n on\n\n "+t._s(new Date(t.post.frontmatter.date).getMonth()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getDate()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getFullYear())+"\n\n - Tags:\n\n "),t._l(t.post.frontmatter.tags,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/tags/"+n}},[t._v(t._s(t._f("capitalize")(n)))]),r!=t.post.frontmatter.tags.length-1?[t._v(", ")]:t._e()],2)}))],2)}),[],!1,null,"0f148fb8",null);e.a=s.exports},265:function(t,e,n){"use strict";n(255)},266:function(t,e,n){"use strict";n(256)},267:function(t,e,n){var r=n(104),i=n(97),s=n(268),a=n(272);t.exports=function(t,e){if(null==t)return{};var n=r(a(t),(function(t){return[t]}));return e=i(e),s(t,n,(function(t,n){return e(t,n[0])}))}},268:function(t,e,n){var r=n(52),i=n(269),s=n(47);t.exports=function(t,e,n){for(var a=-1,o=e.length,u={};++a({comp:null}),computed:{page(){return this.$pagination.paginationIndex+1}},mounted(){n.e(4).then(n.t.bind(null,371,7)).then(t=>{this.comp=t.default})},methods:{clickCallback(t){const e=this.$pagination.getSpecificPageLink(t-1);this.$router.push(e)}}}),a=(n(265),n(7)),o=Object(a.a)(s,(function(){var t=this._self._c;return this.comp?t(this.comp,{tag:"component",attrs:{value:this.page,"page-count":this.$pagination.length,"click-handler":this.clickCallback,"prev-text":this.$pagination.prevText,"next-text":this.$pagination.nextText,"container-class":"pagination","page-class":"page-item"}}):this._e()}),[],!1,null,null,null).exports,u=(n(266),Object(a.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"pagination simple-pagination"},[t.$pagination.hasPrev?e("router-link",{attrs:{to:t.$pagination.prevLink}},[t._v("\n "+t._s(t.$pagination.prevText)+"\n ")]):t._e(),t._v(" "),t.$pagination.hasNext?e("router-link",{attrs:{to:t.$pagination.nextLink}},[t._v("\n "+t._s(t.$pagination.nextText)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports,n(24)),p=n.n(u),c=n(267),l=n.n(c),f={props:{title:{type:[String,Function],required:!1},issueId:{type:[String,Number],required:!1},options:{type:Object,required:!1},shortname:{type:String,required:!1},identifier:{type:String,required:!1},url:{type:String,required:!1},remote_auth_s3:{type:String,required:!1},api_key:{type:String,required:!1},sso_config:{type:Object,required:!1},language:{type:String,required:!1}},computed:{propsWithoutEmptyProperties(){return l()(this.$props,p.a)},commentProps(){return Object.assign({},this.propsWithoutEmptyProperties,this.$frontmatter.comment)},vssueProps(){return Object.assign({title:this.$page.title},this.commentProps)},disqusProps(){return Object.assign({identifier:this.$page.key},this.commentProps)}}},g=(Object(a.a)(f,(function(){var t=this._self._c;return"vssue"===this.$service.comment.service?t("Vssue",this._b({},"Vssue",this.vssueProps,!1)):"disqus"===this.$service.comment.service?t("Disqus",this._b({},"Disqus",this.disqusProps,!1)):this._e()}),[],!1,null,null,null).exports,n(251)),h={name:"IndexPost",components:{LayoutWrap:r.a,Pagination:o,PostMeta:i.a},props:["items","title"],computed:{posts(){return this.items||this.$pagination.pages.sort((t,e)=>new Date(e.frontmatter.date)-new Date(t.frontmatter.date))}},filters:{capitalize:g.capitalize}},v=(n(278),Object(a.a)(h,(function(){var t=this,e=t._self._c;return e("LayoutWrap",[e("main",{staticClass:"page"},[e("div",{staticClass:"theme-default-content"},[e("h1",[t._v(t._s(t.title||"Blog"))]),t._v(" "),t._l(t.posts,(function(n){return e("div",{key:n.path},[e("h2",{staticClass:"index-post-title"},[e("router-link",{attrs:{to:n.path}},[t._v(t._s(n.title||n.frontmatter.title))])],1),t._v(" "),e("PostMeta",{attrs:{post:n}}),t._v(" "),n.frontmatter.coverImage?e("router-link",{attrs:{to:n.path}},[e("img",{staticClass:"cover-image",attrs:{src:n.frontmatter.coverImage}})]):t._e(),t._v(" "),e("hr")],1)})),t._v(" "),t.$pagination.length>1?e("Pagination"):t._e()],2)])])}),[],!1,null,"073f78a2",null));e.default=v.exports},376:function(t,e,n){"use strict";n.r(e);var r=n(281),i=n(251),s={name:"FrontmatterPagination",components:{IndexPost:r.default},computed:{title(){return this.$page.path.startsWith("/blog/tags/")?"Posts tagged with "+Object(i.capitalize)(this.$page.frontmatter.title):"Posts by "+this.$page.frontmatter.title}}},a=n(7),o=Object(a.a)(s,(function(){return(0,this._self._c)("IndexPost",{attrs:{title:this.title}})}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[6,8],{251:function(t,e){t.exports={capitalize:t=>t.replace(/^\w/,t=>t.toUpperCase())}},254:function(t,e,n){},255:function(t,e,n){},256:function(t,e,n){},257:function(t,e,n){},258:function(t,e,n){"use strict";n(254)},260:function(t,e,n){"use strict";var r={name:"PostMeta",props:["post"],filters:{capitalize:n(251).capitalize}},i=(n(258),n(7)),s=Object(i.a)(r,(function(){var t=this,e=t._self._c;return e("p",{staticClass:"meta"},[t._v("\n By\n\n "),t._l(t.post.frontmatter.authors,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/author/"+n}},[t._v(t._s(n))]),r!=t.post.frontmatter.authors.length-1?e("span",[t._v(", ")]):t._e()],1)})),t._v("\n\n on\n\n "+t._s(new Date(t.post.frontmatter.date).getMonth()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getDate()+1)+"/"+t._s(new Date(t.post.frontmatter.date).getFullYear())+"\n\n - Tags:\n\n "),t._l(t.post.frontmatter.tags,(function(n,r){return e("span",{key:n},[e("router-link",{staticClass:"meta-link",attrs:{to:"/blog/tags/"+n}},[t._v(t._s(t._f("capitalize")(n)))]),r!=t.post.frontmatter.tags.length-1?[t._v(", ")]:t._e()],2)}))],2)}),[],!1,null,"0f148fb8",null);e.a=s.exports},265:function(t,e,n){"use strict";n(255)},266:function(t,e,n){"use strict";n(256)},267:function(t,e,n){var r=n(104),i=n(97),s=n(268),a=n(272);t.exports=function(t,e){if(null==t)return{};var n=r(a(t),(function(t){return[t]}));return e=i(e),s(t,n,(function(t,n){return e(t,n[0])}))}},268:function(t,e,n){var r=n(52),i=n(269),s=n(47);t.exports=function(t,e,n){for(var a=-1,o=e.length,u={};++a({comp:null}),computed:{page(){return this.$pagination.paginationIndex+1}},mounted(){n.e(4).then(n.t.bind(null,375,7)).then(t=>{this.comp=t.default})},methods:{clickCallback(t){const e=this.$pagination.getSpecificPageLink(t-1);this.$router.push(e)}}}),a=(n(265),n(7)),o=Object(a.a)(s,(function(){var t=this._self._c;return this.comp?t(this.comp,{tag:"component",attrs:{value:this.page,"page-count":this.$pagination.length,"click-handler":this.clickCallback,"prev-text":this.$pagination.prevText,"next-text":this.$pagination.nextText,"container-class":"pagination","page-class":"page-item"}}):this._e()}),[],!1,null,null,null).exports,u=(n(266),Object(a.a)({},(function(){var t=this,e=t._self._c;return e("div",{staticClass:"pagination simple-pagination"},[t.$pagination.hasPrev?e("router-link",{attrs:{to:t.$pagination.prevLink}},[t._v("\n "+t._s(t.$pagination.prevText)+"\n ")]):t._e(),t._v(" "),t.$pagination.hasNext?e("router-link",{attrs:{to:t.$pagination.nextLink}},[t._v("\n "+t._s(t.$pagination.nextText)+"\n ")]):t._e()],1)}),[],!1,null,null,null).exports,n(24)),p=n.n(u),c=n(267),l=n.n(c),f={props:{title:{type:[String,Function],required:!1},issueId:{type:[String,Number],required:!1},options:{type:Object,required:!1},shortname:{type:String,required:!1},identifier:{type:String,required:!1},url:{type:String,required:!1},remote_auth_s3:{type:String,required:!1},api_key:{type:String,required:!1},sso_config:{type:Object,required:!1},language:{type:String,required:!1}},computed:{propsWithoutEmptyProperties(){return l()(this.$props,p.a)},commentProps(){return Object.assign({},this.propsWithoutEmptyProperties,this.$frontmatter.comment)},vssueProps(){return Object.assign({title:this.$page.title},this.commentProps)},disqusProps(){return Object.assign({identifier:this.$page.key},this.commentProps)}}},g=(Object(a.a)(f,(function(){var t=this._self._c;return"vssue"===this.$service.comment.service?t("Vssue",this._b({},"Vssue",this.vssueProps,!1)):"disqus"===this.$service.comment.service?t("Disqus",this._b({},"Disqus",this.disqusProps,!1)):this._e()}),[],!1,null,null,null).exports,n(251)),h={name:"IndexPost",components:{LayoutWrap:r.a,Pagination:o,PostMeta:i.a},props:["items","title"],computed:{posts(){return this.items||this.$pagination.pages.sort((t,e)=>new Date(e.frontmatter.date)-new Date(t.frontmatter.date))}},filters:{capitalize:g.capitalize}},v=(n(278),Object(a.a)(h,(function(){var t=this,e=t._self._c;return e("LayoutWrap",[e("main",{staticClass:"page"},[e("div",{staticClass:"theme-default-content"},[e("h1",[t._v(t._s(t.title||"Blog"))]),t._v(" "),t._l(t.posts,(function(n){return e("div",{key:n.path},[e("h2",{staticClass:"index-post-title"},[e("router-link",{attrs:{to:n.path}},[t._v(t._s(n.title||n.frontmatter.title))])],1),t._v(" "),e("PostMeta",{attrs:{post:n}}),t._v(" "),n.frontmatter.coverImage?e("router-link",{attrs:{to:n.path}},[e("img",{staticClass:"cover-image",attrs:{src:n.frontmatter.coverImage}})]):t._e(),t._v(" "),e("hr")],1)})),t._v(" "),t.$pagination.length>1?e("Pagination"):t._e()],2)])])}),[],!1,null,"073f78a2",null));e.default=v.exports},380:function(t,e,n){"use strict";n.r(e);var r=n(281),i=n(251),s={name:"FrontmatterPagination",components:{IndexPost:r.default},computed:{title(){return this.$page.path.startsWith("/blog/tags/")?"Posts tagged with "+Object(i.capitalize)(this.$page.frontmatter.title):"Posts by "+this.$page.frontmatter.title}}},a=n(7),o=Object(a.a)(s,(function(){return(0,this._self._c)("IndexPost",{attrs:{title:this.title}})}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/59.f46b900d.js b/assets/js/60.dcd4e6fd.js similarity index 93% rename from assets/js/59.f46b900d.js rename to assets/js/60.dcd4e6fd.js index 96187e8c3..f7f133460 100644 --- a/assets/js/59.f46b900d.js +++ b/assets/js/60.dcd4e6fd.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[59],{424:function(e,t,n){"use strict";n.r(t);var r=n(7),a=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"random-number-generation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#random-number-generation"}},[e._v("#")]),e._v(" Random Number Generation")]),e._v(" "),t("p",[e._v("LDK aims to make no system calls, it is therefore restricted from generating its own randomness.")]),e._v(" "),t("p",[e._v("The sample node implementation uses Rust's "),t("code",[e._v("rand")]),e._v(" crate "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/main.rs#L464-L465",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(" and elsewhere.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[60],{429:function(e,t,n){"use strict";n.r(t);var r=n(7),a=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"random-number-generation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#random-number-generation"}},[e._v("#")]),e._v(" Random Number Generation")]),e._v(" "),t("p",[e._v("LDK aims to make no system calls, it is therefore restricted from generating its own randomness.")]),e._v(" "),t("p",[e._v("The sample node implementation uses Rust's "),t("code",[e._v("rand")]),e._v(" crate "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/main.rs#L464-L465",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(" and elsewhere.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/60.9acae59c.js b/assets/js/61.385e600c.js similarity index 98% rename from assets/js/60.9acae59c.js rename to assets/js/61.385e600c.js index c2d1f182c..eaa28733a 100644 --- a/assets/js/60.9acae59c.js +++ b/assets/js/61.385e600c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[60],{425:function(t,e,r){"use strict";r.r(e);var a=r(7),n=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"transactions"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transactions"}},[t._v("#")]),t._v(" Transactions")]),t._v(" "),e("h2",{attrs:{id:"transaction-filtering"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transaction-filtering"}},[t._v("#")]),t._v(" Transaction Filtering")]),t._v(" "),e("p",[t._v("Clients running a light client may wish to filter for transactions on a separate server, in which case LDK will tell them about transactions to filter for.")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("Filter")]),t._v(" API reference"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("More information is available in the "),e("a",{attrs:{href:"/blockchain_data/introduction"}},[t._v("Blockchain Data guide")]),t._v(".")]),t._v(" "),e("h2",{attrs:{id:"fee-estimation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fee-estimation"}},[t._v("#")]),t._v(" Fee Estimation")]),t._v(" "),e("p",[t._v("LDK let's you decide your source for fee estimation. This could be Bitcoin Core's fee estimation through "),e("code",[t._v("estimatesmartfee")]),t._v(" RPC method or third-party "),e("a",{attrs:{href:"https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/",target:"_blank",rel:"noopener noreferrer"}},[t._v("fee-estimators"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("FeeEstimator")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("LDK's sample node implementation uses Bitcoin Core's fee estimation API "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/bitcoind_client.rs#L98-L154",target:"_blank",rel:"noopener noreferrer"}},[t._v("here."),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"transaction-broadcasting"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transaction-broadcasting"}},[t._v("#")]),t._v(" Transaction Broadcasting")]),t._v(" "),e("p",[t._v("You can broadcast transactions in a few ways, using Bitcoin core or other "),e("a",{attrs:{href:"https://en.bitcoin.it/wiki/Transaction_broadcasting",target:"_blank",rel:"noopener noreferrer"}},[t._v("external API's"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("BroadcasterInterface")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("LDK's sample node implementation uses Bitcoin Core's transaction broadcasting API "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/bitcoind_client.rs#L235-L257",target:"_blank",rel:"noopener noreferrer"}},[t._v("here."),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[61],{430:function(t,e,r){"use strict";r.r(e);var a=r(7),n=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"transactions"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transactions"}},[t._v("#")]),t._v(" Transactions")]),t._v(" "),e("h2",{attrs:{id:"transaction-filtering"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transaction-filtering"}},[t._v("#")]),t._v(" Transaction Filtering")]),t._v(" "),e("p",[t._v("Clients running a light client may wish to filter for transactions on a separate server, in which case LDK will tell them about transactions to filter for.")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/trait.Filter.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("Filter")]),t._v(" API reference"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("More information is available in the "),e("a",{attrs:{href:"/blockchain_data/introduction"}},[t._v("Blockchain Data guide")]),t._v(".")]),t._v(" "),e("h2",{attrs:{id:"fee-estimation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fee-estimation"}},[t._v("#")]),t._v(" Fee Estimation")]),t._v(" "),e("p",[t._v("LDK let's you decide your source for fee estimation. This could be Bitcoin Core's fee estimation through "),e("code",[t._v("estimatesmartfee")]),t._v(" RPC method or third-party "),e("a",{attrs:{href:"https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/",target:"_blank",rel:"noopener noreferrer"}},[t._v("fee-estimators"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.FeeEstimator.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("FeeEstimator")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("LDK's sample node implementation uses Bitcoin Core's fee estimation API "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/bitcoind_client.rs#L98-L154",target:"_blank",rel:"noopener noreferrer"}},[t._v("here."),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"transaction-broadcasting"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#transaction-broadcasting"}},[t._v("#")]),t._v(" Transaction Broadcasting")]),t._v(" "),e("p",[t._v("You can broadcast transactions in a few ways, using Bitcoin core or other "),e("a",{attrs:{href:"https://en.bitcoin.it/wiki/Transaction_broadcasting",target:"_blank",rel:"noopener noreferrer"}},[t._v("external API's"),e("OutboundLink")],1)]),t._v(" "),e("p",[e("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/chain/chaininterface/trait.BroadcasterInterface.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("LDK's "),e("code",[t._v("BroadcasterInterface")]),t._v(" docs"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("LDK's sample node implementation uses Bitcoin Core's transaction broadcasting API "),e("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/bitcoind_client.rs#L235-L257",target:"_blank",rel:"noopener noreferrer"}},[t._v("here."),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/61.6ffa549a.js b/assets/js/62.acc15e11.js similarity index 98% rename from assets/js/61.6ffa549a.js rename to assets/js/62.acc15e11.js index e2e15a6ef..c8e8a416e 100644 --- a/assets/js/61.6ffa549a.js +++ b/assets/js/62.acc15e11.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[61],{426:function(t,e,n){"use strict";n.r(e);var i=n(7),a=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"use-cases-for-ldk"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#use-cases-for-ldk"}},[t._v("#")]),t._v(" Use Cases for LDK")]),t._v(" "),e("p",[t._v("The standard Lightning use case is running a standalone node on one's laptop.\nHere's some other use cases that LDK supports.")]),t._v(" "),e("h2",{attrs:{id:"mobile-devices"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mobile-devices"}},[t._v("#")]),t._v(" Mobile Devices")]),t._v(" "),e("p",[t._v("Mobile devices with Lightning have unique requirements often not well served by\ntoday's Lightning ecosystem. Not only do they need to operate with minimal\nfootprint, they also have intermittent data access and cannot shutdown safely.\nMore importantly, many existing wallets already have business logic to handle\nblockchain data, keys, and storage, and do not wish to duplicate much of that\nlogic to integrate Lightning (at worst fetching the blockchain twice). LDK\noffers a flexible API to allow users to integrate Lightning with their own keys,\nblockchain data, and storage. To allow full flexibility in footprint, the API\nsupports routing data being fetched via the Lightning P2P protocol, an external\nservice, or routes can be calculated off-device. It also provides cross-platform\ncompatibility for free, allowing synchronization of Lightning state across\ndevices and, as long as there is protection from simultaneous updates, users to\naccess their wallet on any device. See the "),e("a",{attrs:{href:"../architecture"}},[t._v("architecure")]),t._v(" page for more\ndetails on the interfaces LDK provides for integration.")]),t._v(" "),e("h2",{attrs:{id:"hsms-hardware-security-modules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#hsms-hardware-security-modules"}},[t._v("#")]),t._v(" HSMs (Hardware Security Modules)")]),t._v(" "),e("p",[t._v("LDK Supports various HSM configurations. In conjunction with the "),e("a",{attrs:{href:"https://vls.tech/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Validating Lightning Signer"),e("OutboundLink")],1),t._v("project, an external HSM can be\nused to verify most protocol details about states before signing, ensuring host\ncompromise cannot steal funds by broadcasting revoked states. For nodes seeking\na higher level of assurance, the entire LDK channel state machine can\nbe run on an offline device, communicating with the outside world via a proxy\nhost which maintains TCP connections with peers. Such a configuration ensures\nall details of the Lightning protocol are enforced without consideration of host\ncompromise.")]),t._v(" "),e("h2",{attrs:{id:"production-lightning-nodes"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#production-lightning-nodes"}},[t._v("#")]),t._v(" Production Lightning Nodes")]),t._v(" "),e("p",[t._v("Many large Bitcoin transactors have large amounts of custom-built infrastructure\nfor interacting with the Bitcoin blockchain. Such tight integration with\nbusiness logic may be difficult with existing Lightning implementations focusing\non standalone operation. For such transactors, LDK offers the possibility of\nintegrating a library in their native runtime, storing and handling Lightning\ndata and events in the same way they do blockchain events.")])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[62],{431:function(t,e,n){"use strict";n.r(e);var i=n(7),a=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"use-cases-for-ldk"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#use-cases-for-ldk"}},[t._v("#")]),t._v(" Use Cases for LDK")]),t._v(" "),e("p",[t._v("The standard Lightning use case is running a standalone node on one's laptop.\nHere's some other use cases that LDK supports.")]),t._v(" "),e("h2",{attrs:{id:"mobile-devices"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mobile-devices"}},[t._v("#")]),t._v(" Mobile Devices")]),t._v(" "),e("p",[t._v("Mobile devices with Lightning have unique requirements often not well served by\ntoday's Lightning ecosystem. Not only do they need to operate with minimal\nfootprint, they also have intermittent data access and cannot shutdown safely.\nMore importantly, many existing wallets already have business logic to handle\nblockchain data, keys, and storage, and do not wish to duplicate much of that\nlogic to integrate Lightning (at worst fetching the blockchain twice). LDK\noffers a flexible API to allow users to integrate Lightning with their own keys,\nblockchain data, and storage. To allow full flexibility in footprint, the API\nsupports routing data being fetched via the Lightning P2P protocol, an external\nservice, or routes can be calculated off-device. It also provides cross-platform\ncompatibility for free, allowing synchronization of Lightning state across\ndevices and, as long as there is protection from simultaneous updates, users to\naccess their wallet on any device. See the "),e("a",{attrs:{href:"../architecture"}},[t._v("architecure")]),t._v(" page for more\ndetails on the interfaces LDK provides for integration.")]),t._v(" "),e("h2",{attrs:{id:"hsms-hardware-security-modules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#hsms-hardware-security-modules"}},[t._v("#")]),t._v(" HSMs (Hardware Security Modules)")]),t._v(" "),e("p",[t._v("LDK Supports various HSM configurations. In conjunction with the "),e("a",{attrs:{href:"https://vls.tech/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Validating Lightning Signer"),e("OutboundLink")],1),t._v("project, an external HSM can be\nused to verify most protocol details about states before signing, ensuring host\ncompromise cannot steal funds by broadcasting revoked states. For nodes seeking\na higher level of assurance, the entire LDK channel state machine can\nbe run on an offline device, communicating with the outside world via a proxy\nhost which maintains TCP connections with peers. Such a configuration ensures\nall details of the Lightning protocol are enforced without consideration of host\ncompromise.")]),t._v(" "),e("h2",{attrs:{id:"production-lightning-nodes"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#production-lightning-nodes"}},[t._v("#")]),t._v(" Production Lightning Nodes")]),t._v(" "),e("p",[t._v("Many large Bitcoin transactors have large amounts of custom-built infrastructure\nfor interacting with the Bitcoin blockchain. Such tight integration with\nbusiness logic may be difficult with existing Lightning implementations focusing\non standalone operation. For such transactors, LDK offers the possibility of\nintegrating a library in their native runtime, storing and handling Lightning\ndata and events in the same way they do blockchain events.")])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/62.8663583e.js b/assets/js/63.1af12a91.js similarity index 96% rename from assets/js/62.8663583e.js rename to assets/js/63.1af12a91.js index 4b8f458d7..fd89308a0 100644 --- a/assets/js/62.8663583e.js +++ b/assets/js/63.1af12a91.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[62],{427:function(e,t,a){"use strict";a.r(t);var n=a(7),i=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"wallet-management"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#wallet-management"}},[e._v("#")]),e._v(" Wallet Management")]),e._v(" "),t("p",[e._v('LDK owns on-chain funds as long as they are claimable as a part of a Lightning output which can be contested - once a channel is closed and all on-chain outputs are spendable only by you, LDK provides you notifications that a UTXO is "yours" again and it is up to you to spend it as you wish.')]),e._v(" "),t("p",[e._v("Additionally, channel funding is accomplished with a generic API which notifies users of the output which needs to appear on-chain, which they can then create a transaction for. Once a transaction is created, LDK handles the rest. This is a large part of our API's goals - making it easier to integrate Lightning into existing on-chain wallets which have their own on-chain logic - without needing to move funds in and out of a separate Lightning wallet with on-chain transactions and a separate private key system.")]),e._v(" "),t("p",[e._v("LDK does not currently provide a sample wallet module, but its sample node implementation uses Bitcoin Core's wallet for UTXO management e.g. "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/main.rs#L245-L260",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[63],{432:function(e,t,a){"use strict";a.r(t);var n=a(7),i=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"wallet-management"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#wallet-management"}},[e._v("#")]),e._v(" Wallet Management")]),e._v(" "),t("p",[e._v('LDK owns on-chain funds as long as they are claimable as a part of a Lightning output which can be contested - once a channel is closed and all on-chain outputs are spendable only by you, LDK provides you notifications that a UTXO is "yours" again and it is up to you to spend it as you wish.')]),e._v(" "),t("p",[e._v("Additionally, channel funding is accomplished with a generic API which notifies users of the output which needs to appear on-chain, which they can then create a transaction for. Once a transaction is created, LDK handles the rest. This is a large part of our API's goals - making it easier to integrate Lightning into existing on-chain wallets which have their own on-chain logic - without needing to move funds in and out of a separate Lightning wallet with on-chain transactions and a separate private key system.")]),e._v(" "),t("p",[e._v("LDK does not currently provide a sample wallet module, but its sample node implementation uses Bitcoin Core's wallet for UTXO management e.g. "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample/blob/2cd778e7acc959689e3b8462c529ffb3509aa1ec/src/main.rs#L245-L260",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/63.b0f86156.js b/assets/js/64.e93fbc83.js similarity index 99% rename from assets/js/63.b0f86156.js rename to assets/js/64.e93fbc83.js index 507be463a..67e8386d2 100644 --- a/assets/js/63.b0f86156.js +++ b/assets/js/64.e93fbc83.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[63],{430:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"key-management"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#key-management"}},[t._v("#")]),t._v(" Key Management")]),t._v(" "),s("p",[t._v("LDK provides a simple default "),s("code",[t._v("KeysManager")]),t._v(" implementation that takes a 32-byte seed for use as a BIP 32 extended key and derives keys from that. Check out the "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust docs"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("However, LDK also allows to customize the way key material and entropy are sourced through custom implementations of the "),s("code",[t._v("NodeSigner")]),t._v(", "),s("code",[t._v("SignerProvider")]),t._v(", and "),s("code",[t._v("EntropySource")]),t._v(" traits located in "),s("code",[t._v("sign")]),t._v(". These traits include basic methods to provide public and private key material, as well as pseudorandom numbers.")]),t._v(" "),s("p",[t._v("A "),s("code",[t._v("KeysManager")]),t._v(" can be constructed simply with only a 32-byte seed and some random integers which ensure uniqueness across restarts (defined as "),s("code",[t._v("starting_time_secs")]),t._v(" and "),s("code",[t._v("starting_time_nanos")]),t._v("):")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in random_32_bytes with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" random_32_bytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" start_time "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_interface_impl "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("sign"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("random_32_bytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" start_time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" start_time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in key_seed with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" key_seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n key_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in seed with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("repeating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" count"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("h1",{attrs:{id:"creating-a-unified-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#creating-a-unified-wallet"}},[t._v("#")]),t._v(" Creating a Unified Wallet")]),t._v(" "),s("p",[t._v('LDK makes it simple to combine an on-chain and off-chain wallet in the same app. This means users don’t need to worry about storing two different recovery phrases. For apps containing a hierarchical deterministic wallet (or "HD Wallet") we recommend using the entropy from a '),s("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc#hardened-child-key-derivation",target:"_blank",rel:"noopener noreferrer"}},[t._v("hardened child key derivation"),s("OutboundLink")],1),t._v(" path for your LDK seed.")]),t._v(" "),s("p",[t._v("Using a "),s("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),s("OutboundLink")],1),t._v("-based wallet the steps would be as follows:")]),t._v(" "),s("ol",[s("li",[t._v("Generate a mnemonic/entropy source.")]),t._v(" "),s("li",[t._v("Build an HD wallet from that. That's now your on-chain wallet, and you can derive any BIP-compliant on-chain wallet/path for it from there.")]),t._v(" "),s("li",[t._v("Derive the private key at "),s("code",[t._v("m/535h")]),t._v(" (or some other custom path). That's 32 bytes and is your starting entropy for your LDK wallet.")]),t._v(" "),s("li",[t._v("Optional: use a custom "),s("code",[t._v("SignerProvider")]),t._v(" implementation to have the BDK wallet provide the destination and shutdown scripts (see "),s("a",{attrs:{href:"#spending-on-chain-funds"}},[t._v("Spending On-Chain Funds")]),t._v(").")])]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("parse_in_normalized")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_seed_normalized")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Other supported networks include mainnet (Bitcoin), Regtest, Signet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" master_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedPrivKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_master")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedPrivKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" master_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ckd_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChildNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Hardened")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("535")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldk_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("private_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secret_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ldk_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" bip32RootKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DescriptorSecretKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TESTNET"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ldkDerivationPath "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/535h"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DescriptorSecretKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" bip32RootKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ldkDerivationPath"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token annotation builtin"}},[t._v("@OptIn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("kotlin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExperimentalUnsignedTypes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" entropy"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secretBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n entropy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Other supported networks include mainnet (Bitcoin), Regtest, Signet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bip32RootKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorSecretKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("testnet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkDerivationPath "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/535h"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkChild "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" bip32RootKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ldkDerivationPath"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkSeed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secretBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ldkSeed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Protection for on-chain wallet")]),t._v(" "),s("p",[t._v("An advantage to this approach is that the LDK entropy is contained within your initial mnemonic and a user only has one master private key to backup and secure. Another added benefit is that if your lightning keys were to be leaked we reduce the exposure to those funds and not the rest of the on-chain wallet.")])]),t._v(" "),s("h1",{attrs:{id:"spending-on-chain-funds"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#spending-on-chain-funds"}},[t._v("#")]),t._v(" Spending On-Chain Funds")]),t._v(" "),s("p",[t._v("When a channel has been closed and some outputs on chain are spendable only by us, LDK provides a "),s("code",[t._v("util::events::Event::SpendableOutputs")]),t._v(" event in return from "),s("code",[t._v("ChannelMonitor::get_and_clear_pending_events()")]),t._v(". It contains a list of "),s("code",[t._v("sign::SpendableOutputDescriptor")]),t._v(" objects which describe the output and provide all necessary information to spend it.")]),t._v(" "),s("p",[t._v("If you're using "),s("code",[t._v("KeysManager")]),t._v(" directly, a utility method is provided which can generate a signed transaction given a list of "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects. "),s("code",[t._v("KeysManager::spend_spendable_outputs")]),t._v(" can be called any time after receiving the "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects to build a spending transaction, including delaying until sending funds to an external destination or opening a new channel. Note that if you open new channels directly with "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects, you must ensure all closing/destination scripts provided to LDK are SegWit (either native or P2SH-wrapped).")]),t._v(" "),s("p",[t._v("If you are not using "),s("code",[t._v("KeysManager")]),t._v(" for keys generation, you must re-derive the private keys yourself. Any "),s("code",[t._v("ChannelSigner")]),t._v(" object must provide a unique id via the "),s("code",[t._v("channel_keys_id")]),t._v(" function, whose value is provided back to you in the "),s("code",[t._v("SpendableOutputs")]),t._v(" objects. A "),s("code",[t._v("SpendableOutputDescriptor::StaticOutput")]),t._v(" element does not have this information as the output is sent to an output which used only "),s("code",[t._v("KeysInterface")]),t._v(" data, not per-channel data.")]),t._v(" "),s("p",[t._v("In order to make the outputs from channel closing spendable by a third-party wallet, a middleground between using the default "),s("code",[t._v("KeysManager")]),t._v(" and an entirely custom implementation of "),s("code",[t._v("SignerProvider")]),t._v("/"),s("code",[t._v("NodeSigner")]),t._v("/"),s("code",[t._v("EntropySource")]),t._v(" could be to implement a wrapper around "),s("code",[t._v("KeysManager")]),t._v(". Such a wrapper would need to override the respective methods returning the destination and shutdown scripts while simply dropping any instances of "),s("code",[t._v("SpendableOutputDescriptor::StaticOutput")]),t._v(", as these then could be spent by the third-party wallet from which the scripts had been derived.")]),t._v(" "),s("p",[t._v("For example, a wrapper based on BDK's "),s("a",{attrs:{href:"https://docs.rs/bdk/*/bdk/wallet/struct.Wallet.html",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("Wallet")]),s("OutboundLink")],1),t._v(" could look like this:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tinner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\twallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutex")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_secs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_nanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutex")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_secs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_nanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signing")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxOut")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tchange_destination_script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feerate_sat_per_1000_weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tlocktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PackedLockTime")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" secp_ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" only_non_static "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("descriptors\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StaticOutput")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("copied")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("collect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t\tonly_non_static"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\toutputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tchange_destination_script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tfeerate_sat_per_1000_weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tlocktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tsecp_ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignerProvider")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("Signer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InMemorySigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_destination_script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to retrieve new address from wallet: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_shutdown_scriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to retrieve new address from wallet: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payload "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WitnessProgram")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" program "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_witness_program")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Invalid shutdown script: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t_ "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Tried to use a non-witness address. This must not ever happen."')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... and redirect all other trait method implementations to the `inner` `KeysManager`.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u128")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_keys_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_keys_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DecodeError")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NodeSigner")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... snip")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EntropySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... snip")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("LDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeSecs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeNano"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Int"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" KeysManager\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Wallet\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" signerProvider"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LDKSignerProvider\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeNano"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet\n signerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("LDKSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldkkeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("TxOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Int"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option_u32Z\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_TransactionNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" it "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StaticOutput "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toTypedArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" LDKSignerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SignerProviderInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LDKKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Boolean"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UInt128"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" WriteableEcdsaChannelSigner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_WriteableEcdsaChannelSignerDecodeErrorZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token annotation builtin"}},[t._v("@OptIn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExperimentalUnsignedTypes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_destination_script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_CVec_u8ZNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("AddressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("New"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" Result_CVec_u8ZNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Only applies to cooperative close transactions.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_shutdown_scriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_ShutdownScriptNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("AddressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("New"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("when")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" payload"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Payload "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WitnessProgram "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("when")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"V0"')])]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"V16"')])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("substring")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toIntOrNull")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?:")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Default to 0 if it doesn\'t match any "V0" to "V16"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ShutdownScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_witness_program")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WitnessVersion")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Result_ShutdownScriptNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_ShutdownScriptInvalidShutdownScriptZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_ShutdownScriptInvalidShutdownScriptZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Result_ShutdownScriptNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyKeysManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet\n signerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxOut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_TransactionNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filter "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StaticOutput")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" locktime\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" res\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignerProvider")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("weak")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getDestinationScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ScriptNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ScriptNoneZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getShutdownScriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ShutdownScriptNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payload "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("witnessProgram")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("`version`"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" `program`"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" payload "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" version "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v0"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v5"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v6"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v7"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v8"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v9"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v10"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v11"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("11")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v12"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v13"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v14"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("14")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v15"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v16"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("newWitnessProgram")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ShutdownScriptNoneZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... and redirect all other trait method implementations to the `inner` `KeysManager`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("deriveChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WriteableEcdsaChannelSigner")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("deriveChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelKeysId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("generateChannelKeysId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateChannelKeysId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userChannelId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("readChanSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_WriteableEcdsaChannelSignerDecodeErrorZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("readChanSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])})],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[64],{434:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"key-management"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#key-management"}},[t._v("#")]),t._v(" Key Management")]),t._v(" "),s("p",[t._v("LDK provides a simple default "),s("code",[t._v("KeysManager")]),t._v(" implementation that takes a 32-byte seed for use as a BIP 32 extended key and derives keys from that. Check out the "),s("a",{attrs:{href:"https://docs.rs/lightning/*/lightning/sign/struct.KeysManager.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust docs"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("However, LDK also allows to customize the way key material and entropy are sourced through custom implementations of the "),s("code",[t._v("NodeSigner")]),t._v(", "),s("code",[t._v("SignerProvider")]),t._v(", and "),s("code",[t._v("EntropySource")]),t._v(" traits located in "),s("code",[t._v("sign")]),t._v(". These traits include basic methods to provide public and private key material, as well as pseudorandom numbers.")]),t._v(" "),s("p",[t._v("A "),s("code",[t._v("KeysManager")]),t._v(" can be constructed simply with only a 32-byte seed and some random integers which ensure uniqueness across restarts (defined as "),s("code",[t._v("starting_time_secs")]),t._v(" and "),s("code",[t._v("starting_time_nanos")]),t._v("):")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in random_32_bytes with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" random_32_bytes "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" start_time "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_interface_impl "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("lightning"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("sign"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("random_32_bytes"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" start_time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" start_time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in key_seed with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" key_seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n key_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fill in seed with secure random data, or, on restart, reload the seed from disk.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("repeating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" count"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("h1",{attrs:{id:"creating-a-unified-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#creating-a-unified-wallet"}},[t._v("#")]),t._v(" Creating a Unified Wallet")]),t._v(" "),s("p",[t._v('LDK makes it simple to combine an on-chain and off-chain wallet in the same app. This means users don’t need to worry about storing two different recovery phrases. For apps containing a hierarchical deterministic wallet (or "HD Wallet") we recommend using the entropy from a '),s("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc#hardened-child-key-derivation",target:"_blank",rel:"noopener noreferrer"}},[t._v("hardened child key derivation"),s("OutboundLink")],1),t._v(" path for your LDK seed.")]),t._v(" "),s("p",[t._v("Using a "),s("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BDK"),s("OutboundLink")],1),t._v("-based wallet the steps would be as follows:")]),t._v(" "),s("ol",[s("li",[t._v("Generate a mnemonic/entropy source.")]),t._v(" "),s("li",[t._v("Build an HD wallet from that. That's now your on-chain wallet, and you can derive any BIP-compliant on-chain wallet/path for it from there.")]),t._v(" "),s("li",[t._v("Derive the private key at "),s("code",[t._v("m/535h")]),t._v(" (or some other custom path). That's 32 bytes and is your starting entropy for your LDK wallet.")]),t._v(" "),s("li",[t._v("Optional: use a custom "),s("code",[t._v("SignerProvider")]),t._v(" implementation to have the BDK wallet provide the destination and shutdown scripts (see "),s("a",{attrs:{href:"#spending-on-chain-funds"}},[t._v("Spending On-Chain Funds")]),t._v(").")])]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("parse_in_normalized")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_seed_normalized")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Other supported networks include mainnet (Bitcoin), Regtest, Signet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" master_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedPrivKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_master")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Testnet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedPrivKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" master_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ckd_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ChildNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Hardened")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" index"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("535")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldk_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("private_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secret_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" cur "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("now")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("duration_since")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SystemTime")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("UNIX_EPOCH")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keys_manager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ldk_seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_secs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cur"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("subsec_nanos")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" bip32RootKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DescriptorSecretKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TESTNET"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ldkDerivationPath "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/535h"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" DescriptorSecretKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" bip32RootKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ldkDerivationPath"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token annotation builtin"}},[t._v("@OptIn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("kotlin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ExperimentalUnsignedTypes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" entropy"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secretBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n entropy"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("System"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("currentTimeMillis")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toInt")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use BDK to create and build the HD wallet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sock lyrics village put galaxy famous pass act ship second diagram pull"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Other supported networks include mainnet (Bitcoin), Regtest, Signet")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bip32RootKey "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorSecretKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("testnet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token nil constant"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkDerivationPath "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/535h"')])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkChild "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" bip32RootKey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ldkDerivationPath"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ldkSeed "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkChild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("secretBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSDate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("timeIntervalSince1970"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" timestampNanos "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("truncating"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NSNumber")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Seed the LDK KeysManager with the private key at m/535h")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" keysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ldkSeed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampSeconds"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tstartingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" timestampNanos\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])]},proxy:!0}])}),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("Protection for on-chain wallet")]),t._v(" "),s("p",[t._v("An advantage to this approach is that the LDK entropy is contained within your initial mnemonic and a user only has one master private key to backup and secure. Another added benefit is that if your lightning keys were to be leaked we reduce the exposure to those funds and not the rest of the on-chain wallet.")])]),t._v(" "),s("h1",{attrs:{id:"spending-on-chain-funds"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#spending-on-chain-funds"}},[t._v("#")]),t._v(" Spending On-Chain Funds")]),t._v(" "),s("p",[t._v("When a channel has been closed and some outputs on chain are spendable only by us, LDK provides a "),s("code",[t._v("util::events::Event::SpendableOutputs")]),t._v(" event in return from "),s("code",[t._v("ChannelMonitor::get_and_clear_pending_events()")]),t._v(". It contains a list of "),s("code",[t._v("sign::SpendableOutputDescriptor")]),t._v(" objects which describe the output and provide all necessary information to spend it.")]),t._v(" "),s("p",[t._v("If you're using "),s("code",[t._v("KeysManager")]),t._v(" directly, a utility method is provided which can generate a signed transaction given a list of "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects. "),s("code",[t._v("KeysManager::spend_spendable_outputs")]),t._v(" can be called any time after receiving the "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects to build a spending transaction, including delaying until sending funds to an external destination or opening a new channel. Note that if you open new channels directly with "),s("code",[t._v("SpendableOutputDescriptor")]),t._v(" objects, you must ensure all closing/destination scripts provided to LDK are SegWit (either native or P2SH-wrapped).")]),t._v(" "),s("p",[t._v("If you are not using "),s("code",[t._v("KeysManager")]),t._v(" for keys generation, you must re-derive the private keys yourself. Any "),s("code",[t._v("ChannelSigner")]),t._v(" object must provide a unique id via the "),s("code",[t._v("channel_keys_id")]),t._v(" function, whose value is provided back to you in the "),s("code",[t._v("SpendableOutputs")]),t._v(" objects. A "),s("code",[t._v("SpendableOutputDescriptor::StaticOutput")]),t._v(" element does not have this information as the output is sent to an output which used only "),s("code",[t._v("KeysInterface")]),t._v(" data, not per-channel data.")]),t._v(" "),s("p",[t._v("In order to make the outputs from channel closing spendable by a third-party wallet, a middleground between using the default "),s("code",[t._v("KeysManager")]),t._v(" and an entirely custom implementation of "),s("code",[t._v("SignerProvider")]),t._v("/"),s("code",[t._v("NodeSigner")]),t._v("/"),s("code",[t._v("EntropySource")]),t._v(" could be to implement a wrapper around "),s("code",[t._v("KeysManager")]),t._v(". Such a wrapper would need to override the respective methods returning the destination and shutdown scripts while simply dropping any instances of "),s("code",[t._v("SpendableOutputDescriptor::StaticOutput")]),t._v(", as these then could be spent by the third-party wallet from which the scripts had been derived.")]),t._v(" "),s("p",[t._v("For example, a wrapper based on BDK's "),s("a",{attrs:{href:"https://docs.rs/bdk/*/bdk/wallet/struct.Wallet.html",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("Wallet")]),s("OutboundLink")],1),t._v(" could look like this:")]),t._v(" "),s("CodeSwitcher",{attrs:{languages:{rust:"Rust",kotlin:"Kotlin",swift:"Swift"}},scopedSlots:t._u([{key:"rust",fn:function(){return[s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tinner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\twallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutex")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\tseed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_secs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_nanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Arc")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mutex")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_secs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" starting_time_nanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signing")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxOut")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tchange_destination_script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feerate_sat_per_1000_weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tlocktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Option")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PackedLockTime")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" secp_ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("C")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Transaction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" only_non_static "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("descriptors\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("filter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StaticOutput")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("copied")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("collect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t\tonly_non_static"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\toutputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tchange_destination_script"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tfeerate_sat_per_1000_weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tlocktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tsecp_ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignerProvider")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("Signer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InMemorySigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_destination_script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to retrieve new address from wallet: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_shutdown_scriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Failed to retrieve new address from wallet: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("match")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("payload "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WitnessProgram")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" program "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_witness_program")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("map_err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("e"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("eprintln!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Invalid shutdown script: {:?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\t\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t_ "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("panic!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Tried to use a non-witness address. This must not ever happen."')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... and redirect all other trait method implementations to the `inner` `KeysManager`.")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u128")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user_channel_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_keys_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channel_value_satoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channel_keys_id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("u8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("Self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DecodeError")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NodeSigner")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... snip")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EntropySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("D")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BatchDatabase")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... snip")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"kotlin",fn:function(){return[s("div",{staticClass:"language-kotlin extra-class"},[s("pre",{pre:!0,attrs:{class:"language-kotlin"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("LDKKeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeSecs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeNano"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Int"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inner")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" KeysManager\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Wallet\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" signerProvider"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LDKSignerProvider\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" KeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startTimeNano"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet\n signerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("LDKSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ldkkeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("this")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("TxOut"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Int"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Option_u32Z\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_TransactionNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Array"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("filter")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" it "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" SpendableOutputDescriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StaticOutput "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toTypedArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spend_spendable_outputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" LDKSignerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" SignerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("SignerProviderInterface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" LDKKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Boolean"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" UInt128"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_channel_keys_id")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Long"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" WriteableEcdsaChannelSigner "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_channel_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" ByteArray"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_WriteableEcdsaChannelSignerDecodeErrorZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_SignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("read_chan_signer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token annotation builtin"}},[t._v("@OptIn")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExperimentalUnsignedTypes"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_destination_script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_CVec_u8ZNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("AddressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("New"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" Result_CVec_u8ZNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Only applies to cooperative close transactions.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fun")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_shutdown_scriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Result_ShutdownScriptNoneZ "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ldkkeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("AddressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("New"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("when")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" payload"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" Payload "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("is")]),t._v(" Payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WitnessProgram "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("when")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"V0"')])]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token string-literal singleline"}},[s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"V16"')])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("substring")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toIntOrNull")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?:")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Default to 0 if it doesn\'t match any "V0" to "V16"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("val")]),t._v(" result "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ShutdownScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_witness_program")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WitnessVersion")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n payload"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toUByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toByteArray")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Result_ShutdownScriptNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ok")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" Result_ShutdownScriptInvalidShutdownScriptZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Result_ShutdownScriptInvalidShutdownScriptZ_OK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Result_ShutdownScriptNoneZ"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])]},proxy:!0},{key:"swift",fn:function(){return[s("div",{staticClass:"language-swift extra-class"},[s("pre",{pre:!0,attrs:{class:"language-swift"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyKeysManager")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("init")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BitcoinDevKit")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeysManager")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" seed"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" startingTimeSecs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" startingTimeNanos"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet\n signerProvider "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n signerProvider"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("myKeysManager "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We drop all occurences of `SpendableOutputDescriptor::StaticOutput` (since they will be")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// spendable by the BDK wallet) and forward any other descriptors to")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// `KeysManager::spend_spendable_outputs`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Note you should set `locktime` to the current block height to mitigate fee sniping.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// See https://bitcoinops.org/en/topics/fee-sniping/ for more information.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxOut")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt32")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_TransactionNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SpendableOutputDescriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("filter "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValueType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StaticOutput")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("spendSpendableOutputs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" onlyNonStatic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" outputs"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" changeDestinationScript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" feerateSatPer1000Weight"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n locktime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" locktime\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" res\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MySignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignerProvider")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("weak")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyKeysManager")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We return the destination and shutdown scripts derived by the BDK wallet.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getDestinationScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ScriptNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ScriptNoneZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("toBytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("getShutdownScriptpubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ShutdownScriptNoneZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("do")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("new"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" payload "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("payload")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("witnessProgram")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("`version`"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" `program`"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" payload "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" version "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v0"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v2"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v3"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v4"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v5"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v6"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v7"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v8"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v9"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("9")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v10"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v11"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("11")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v12"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v13"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v14"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("14")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v15"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v16"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n ver "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" res "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ShutdownScript")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("newWitnessProgram")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("version"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ver"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" program"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("isOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_ShutdownScriptNoneZ")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithOk")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" res"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("getValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("initWithErr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... and redirect all other trait method implementations to the `inner` `KeysManager`.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("deriveChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WriteableEcdsaChannelSigner")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("deriveChannelSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelKeysId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelKeysId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("generateChannelKeysId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateChannelKeysId")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" inbound"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" channelValueSatoshis"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n userChannelId"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" userChannelId\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("override")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("readChanSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UInt8")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Bindings")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Result_WriteableEcdsaChannelSignerDecodeErrorZ")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" myKeysManager"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("inner"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("asSignerProvider")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("readChanSigner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]},proxy:!0}])})],1)}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/64.2df52a31.js b/assets/js/65.334c2c89.js similarity index 88% rename from assets/js/64.2df52a31.js rename to assets/js/65.334c2c89.js index c4ca0e3e7..ba3160748 100644 --- a/assets/js/64.2df52a31.js +++ b/assets/js/65.334c2c89.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[64],{428:function(t,s,n){"use strict";n.r(s);var a=n(7),i=Object(a.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"language-bindings"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#language-bindings"}},[this._v("#")]),this._v(" Language Bindings")]),this._v(" "),t("p",[this._v("TODO")]),this._v(" "),t("p",[this._v("state of language bindings on a per-language basis")])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[65],{433:function(t,s,n){"use strict";n.r(s);var a=n(7),i=Object(a.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"language-bindings"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#language-bindings"}},[this._v("#")]),this._v(" Language Bindings")]),this._v(" "),t("p",[this._v("TODO")]),this._v(" "),t("p",[this._v("state of language bindings on a per-language basis")])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/65.fb3a6f9e.js b/assets/js/66.b8a9a4c0.js similarity index 86% rename from assets/js/65.fb3a6f9e.js rename to assets/js/66.b8a9a4c0.js index d87accac3..670c39f0d 100644 --- a/assets/js/65.fb3a6f9e.js +++ b/assets/js/66.b8a9a4c0.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[65],{429:function(t,s,e){"use strict";e.r(s);var a=e(7),n=Object(a.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"data-persistence"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#data-persistence"}},[this._v("#")]),this._v(" Data Persistence")]),this._v(" "),t("p",[this._v("TODO")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[66],{435:function(t,s,e){"use strict";e.r(s);var a=e(7),n=Object(a.a)({},(function(){var t=this._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[t("h1",{attrs:{id:"data-persistence"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#data-persistence"}},[this._v("#")]),this._v(" Data Persistence")]),this._v(" "),t("p",[this._v("TODO")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/66.ae5775a2.js b/assets/js/67.79bd6148.js similarity index 99% rename from assets/js/66.ae5775a2.js rename to assets/js/67.79bd6148.js index fde464b0f..03a0b605e 100644 --- a/assets/js/66.ae5775a2.js +++ b/assets/js/67.79bd6148.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[66],{431:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"running-a-sample-ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#running-a-sample-ldk-node"}},[e._v("#")]),e._v(" Running a sample LDK node")]),e._v(" "),t("p",[e._v("Let's run our first LDK node. We'll ensure we have a compatible Rust toolchain installed, setup Polar to create a local Lightning network and then start running the node.")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("Not recommended for production use!")]),e._v(" "),t("p",[e._v("This guide is a quick start to get you up and running with an LDK node. It serves as a playground and a foundation to build upon and is NOT recommended for production environments. LDK doesn't come with a pre-packaged node but gives you the tools to build a node from scratch!")])]),e._v(" "),t("h2",{attrs:{id:"installing-rust"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#installing-rust"}},[e._v("#")]),e._v(" Installing Rust")]),e._v(" "),t("p",[e._v("If you already have a working installation of the latest Rust compiler, feel free to skip to the next section.")]),e._v(" "),t("p",[e._v("To install the latest version of Rust, we recommend using "),t("code",[e._v("rustup")]),e._v(". Install "),t("code",[e._v("rustup")]),e._v(" by following the instructions on "),t("a",{attrs:{href:"https://rustup.rs/",target:"_blank",rel:"noopener noreferrer"}},[e._v("its website"),t("OutboundLink")],1),e._v(". Once "),t("code",[e._v("rustup")]),e._v(" is installed, ensure the latest toolchain is installed by running the command:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("rustup default stable\n")])])]),t("h2",{attrs:{id:"setup-polar"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#setup-polar"}},[e._v("#")]),e._v(" Setup Polar")]),e._v(" "),t("p",[e._v("Next, let's setup Polar, which was built to help Lightning Network application developers quickly spin up one or more networks locally on their computers in regtest mode.")]),e._v(" "),t("p",[e._v("Polar can be "),t("a",{attrs:{href:"https://lightningpolar.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("downloaded"),t("OutboundLink")],1),e._v(" for MacOS, Linux, and Windows. The source code is hosted "),t("a",{attrs:{href:"https://github.com/jamaljsr/polar/releases/",target:"_blank",rel:"noopener noreferrer"}},[e._v("on Github"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Mac and Windows users will need to install "),t("a",{attrs:{href:"https://www.docker.com/products/docker-desktop",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Desktop"),t("OutboundLink")],1),e._v(" as a dependency before using Polar. Linux users will need to download both "),t("a",{attrs:{href:"https://docs.docker.com/get-docker/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Server"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://docs.docker.com/compose/install/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Compose"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("After downloading, installing, and running Polar, spin up a new cluster of LND, Core Lightning, eclair, and bitcoind nodes. This will create a Docker container within which Polar will operate.")]),e._v(" "),t("p",[e._v("Click the orange "),t("strong",[e._v("Create Network")]),e._v(" button and Polar should display a new interface.")]),e._v(" "),t("p",[e._v("Press the orange "),t("strong",[e._v("Start")]),e._v(" button in the top right corner to start your local network. It takes a couple seconds for the nodes to boot up, but the indicator lights will eventually turn green signaling that the process has completed.")]),e._v(" "),t("h2",{attrs:{id:"running-the-ldk-sample-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#running-the-ldk-sample-node"}},[e._v("#")]),e._v(" Running the LDK Sample Node")]),e._v(" "),t("p",[e._v("Start by cloning the LDK sample node from Github and changing into the new directory")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("git clone https://github.com/lightningdevkit/ldk-sample\ncd ldk-sample\n")])])]),t("p",[e._v("Now, run the following command:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("cargo run polaruser:polarpass@127.0.0.1:18443 ./ 9732 regtest hellolightning 0.0.0.0:9732\n")])])]),t("p",[e._v("If you have a different setup that doesn't involve Polar you can modify this command so that it contains different credentials.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("cargo run :@: [] [] [] []\n")])])]),t("p",[t("code",[e._v("bitcoind")]),e._v("'s RPC username and password likely can be found through "),t("code",[e._v("cat ~/.bitcoin/.cookie")]),e._v(".")]),e._v(" "),t("p",[t("code",[e._v("bitcoin-network")]),e._v(": defaults to "),t("code",[e._v("testnet")]),e._v(". Options: "),t("code",[e._v("testnet")]),e._v(", "),t("code",[e._v("regtest")]),e._v(", and "),t("code",[e._v("signet")]),e._v(".")]),e._v(" "),t("p",[t("code",[e._v("ldk-peer-listening-port")]),e._v(": defaults to 9735.")]),e._v(" "),t("p",[t("code",[e._v("announced-node-name")]),e._v(" and "),t("code",[e._v("announced-listen-addr")]),e._v(" : default to nothing, disabling any public announcements of this node.")]),e._v(" "),t("p",[t("code",[e._v("announced-node-name")]),e._v(": can be any string up to 32 bytes in length, representing this node's alias.\n"),t("code",[e._v("announced-listen-addr")]),e._v(": can be set to an IPv4 or IPv6 address to announce that as a publicly-connectable address for this node.")]),e._v(" "),t("p",[e._v("Your LDK node should now be in action!")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('LDK startup successful. To view available commands: "help".\nLDK logs are available at /.ldk/logs\nLocal Node ID is 02e8788eb41ac1731352d87ced719afce91a1201cf0d6cca12ee79502db1b0e317.\n')])])]),t("p",[e._v("If you want to connect to another node you created with Polar select the node there. In the "),t("strong",[e._v("Connect")]),e._v(" tab you can copy the "),t("code",[e._v("P2P External")]),e._v(" connection info. Running "),t("code",[e._v("connectpeer")]),e._v(" with that will get you connected.")]),e._v(" "),t("p",[e._v("To check out the complete reference for constructing a Lightning node with LDK check out the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("Github repo"),t("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[67],{436:function(e,t,n){"use strict";n.r(t);var o=n(7),a=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"running-a-sample-ldk-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#running-a-sample-ldk-node"}},[e._v("#")]),e._v(" Running a sample LDK node")]),e._v(" "),t("p",[e._v("Let's run our first LDK node. We'll ensure we have a compatible Rust toolchain installed, setup Polar to create a local Lightning network and then start running the node.")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("Not recommended for production use!")]),e._v(" "),t("p",[e._v("This guide is a quick start to get you up and running with an LDK node. It serves as a playground and a foundation to build upon and is NOT recommended for production environments. LDK doesn't come with a pre-packaged node but gives you the tools to build a node from scratch!")])]),e._v(" "),t("h2",{attrs:{id:"installing-rust"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#installing-rust"}},[e._v("#")]),e._v(" Installing Rust")]),e._v(" "),t("p",[e._v("If you already have a working installation of the latest Rust compiler, feel free to skip to the next section.")]),e._v(" "),t("p",[e._v("To install the latest version of Rust, we recommend using "),t("code",[e._v("rustup")]),e._v(". Install "),t("code",[e._v("rustup")]),e._v(" by following the instructions on "),t("a",{attrs:{href:"https://rustup.rs/",target:"_blank",rel:"noopener noreferrer"}},[e._v("its website"),t("OutboundLink")],1),e._v(". Once "),t("code",[e._v("rustup")]),e._v(" is installed, ensure the latest toolchain is installed by running the command:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("rustup default stable\n")])])]),t("h2",{attrs:{id:"setup-polar"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#setup-polar"}},[e._v("#")]),e._v(" Setup Polar")]),e._v(" "),t("p",[e._v("Next, let's setup Polar, which was built to help Lightning Network application developers quickly spin up one or more networks locally on their computers in regtest mode.")]),e._v(" "),t("p",[e._v("Polar can be "),t("a",{attrs:{href:"https://lightningpolar.com/",target:"_blank",rel:"noopener noreferrer"}},[e._v("downloaded"),t("OutboundLink")],1),e._v(" for MacOS, Linux, and Windows. The source code is hosted "),t("a",{attrs:{href:"https://github.com/jamaljsr/polar/releases/",target:"_blank",rel:"noopener noreferrer"}},[e._v("on Github"),t("OutboundLink")],1)]),e._v(" "),t("p",[e._v("Mac and Windows users will need to install "),t("a",{attrs:{href:"https://www.docker.com/products/docker-desktop",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Desktop"),t("OutboundLink")],1),e._v(" as a dependency before using Polar. Linux users will need to download both "),t("a",{attrs:{href:"https://docs.docker.com/get-docker/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Server"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://docs.docker.com/compose/install/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Docker Compose"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("After downloading, installing, and running Polar, spin up a new cluster of LND, Core Lightning, eclair, and bitcoind nodes. This will create a Docker container within which Polar will operate.")]),e._v(" "),t("p",[e._v("Click the orange "),t("strong",[e._v("Create Network")]),e._v(" button and Polar should display a new interface.")]),e._v(" "),t("p",[e._v("Press the orange "),t("strong",[e._v("Start")]),e._v(" button in the top right corner to start your local network. It takes a couple seconds for the nodes to boot up, but the indicator lights will eventually turn green signaling that the process has completed.")]),e._v(" "),t("h2",{attrs:{id:"running-the-ldk-sample-node"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#running-the-ldk-sample-node"}},[e._v("#")]),e._v(" Running the LDK Sample Node")]),e._v(" "),t("p",[e._v("Start by cloning the LDK sample node from Github and changing into the new directory")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("git clone https://github.com/lightningdevkit/ldk-sample\ncd ldk-sample\n")])])]),t("p",[e._v("Now, run the following command:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("cargo run polaruser:polarpass@127.0.0.1:18443 ./ 9732 regtest hellolightning 0.0.0.0:9732\n")])])]),t("p",[e._v("If you have a different setup that doesn't involve Polar you can modify this command so that it contains different credentials.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("cargo run :@: [] [] [] []\n")])])]),t("p",[t("code",[e._v("bitcoind")]),e._v("'s RPC username and password likely can be found through "),t("code",[e._v("cat ~/.bitcoin/.cookie")]),e._v(".")]),e._v(" "),t("p",[t("code",[e._v("bitcoin-network")]),e._v(": defaults to "),t("code",[e._v("testnet")]),e._v(". Options: "),t("code",[e._v("testnet")]),e._v(", "),t("code",[e._v("regtest")]),e._v(", and "),t("code",[e._v("signet")]),e._v(".")]),e._v(" "),t("p",[t("code",[e._v("ldk-peer-listening-port")]),e._v(": defaults to 9735.")]),e._v(" "),t("p",[t("code",[e._v("announced-node-name")]),e._v(" and "),t("code",[e._v("announced-listen-addr")]),e._v(" : default to nothing, disabling any public announcements of this node.")]),e._v(" "),t("p",[t("code",[e._v("announced-node-name")]),e._v(": can be any string up to 32 bytes in length, representing this node's alias.\n"),t("code",[e._v("announced-listen-addr")]),e._v(": can be set to an IPv4 or IPv6 address to announce that as a publicly-connectable address for this node.")]),e._v(" "),t("p",[e._v("Your LDK node should now be in action!")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('LDK startup successful. To view available commands: "help".\nLDK logs are available at /.ldk/logs\nLocal Node ID is 02e8788eb41ac1731352d87ced719afce91a1201cf0d6cca12ee79502db1b0e317.\n')])])]),t("p",[e._v("If you want to connect to another node you created with Polar select the node there. In the "),t("strong",[e._v("Connect")]),e._v(" tab you can copy the "),t("code",[e._v("P2P External")]),e._v(" connection info. Running "),t("code",[e._v("connectpeer")]),e._v(" with that will get you connected.")]),e._v(" "),t("p",[e._v("To check out the complete reference for constructing a Lightning node with LDK check out the "),t("a",{attrs:{href:"https://github.com/lightningdevkit/ldk-sample",target:"_blank",rel:"noopener noreferrer"}},[e._v("Github repo"),t("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/67.bb3290e3.js b/assets/js/68.af1b181f.js similarity index 99% rename from assets/js/67.bb3290e3.js rename to assets/js/68.af1b181f.js index e533fa79e..e7f9b5ebe 100644 --- a/assets/js/67.bb3290e3.js +++ b/assets/js/68.af1b181f.js @@ -1,3 +1,3 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[67],{368:function(t,e,n){ +(window.webpackJsonp=window.webpackJsonp||[]).push([[68],{372:function(t,e,n){ /*! For license information please see mermaid.min.js.LICENSE.txt */ "undefined"!=typeof self&&self,t.exports=(()=>{var t={1362:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,6],n=[1,7],r=[1,8],i=[1,9],a=[1,12],o=[1,11],s=[1,15,24],c=[1,19],u=[1,31],l=[1,34],h=[1,32],f=[1,33],d=[1,35],p=[1,36],y=[1,37],g=[1,38],m=[1,41],v=[1,42],b=[1,43],_=[1,44],x=[15,24],w=[1,56],k=[1,57],T=[1,58],E=[1,59],C=[1,60],S=[1,61],A=[15,24,31,38,39,47,50,51,52,53,54,55,60,62],M=[15,24,29,31,38,39,43,47,50,51,52,53,54,55,60,62,77,78,79,80],N=[7,8,9,10,15,18,22,24],D=[47,77,78,79,80],O=[47,54,55,77,78,79,80],B=[47,50,51,52,53,77,78,79,80],L=[15,24,31],I=[1,93],R={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,directive:6,direction_tb:7,direction_bt:8,direction_rl:9,direction_lr:10,graphConfig:11,openDirective:12,typeDirective:13,closeDirective:14,NEWLINE:15,":":16,argDirective:17,open_directive:18,type_directive:19,arg_directive:20,close_directive:21,CLASS_DIAGRAM:22,statements:23,EOF:24,statement:25,className:26,alphaNumToken:27,classLiteralName:28,GENERICTYPE:29,relationStatement:30,LABEL:31,classStatement:32,methodStatement:33,annotationStatement:34,clickStatement:35,cssClassStatement:36,CLASS:37,STYLE_SEPARATOR:38,STRUCT_START:39,members:40,STRUCT_STOP:41,ANNOTATION_START:42,ANNOTATION_END:43,MEMBER:44,SEPARATOR:45,relation:46,STR:47,relationType:48,lineType:49,AGGREGATION:50,EXTENSION:51,COMPOSITION:52,DEPENDENCY:53,LINE:54,DOTTED_LINE:55,CALLBACK:56,LINK:57,LINK_TARGET:58,CLICK:59,CALLBACK_NAME:60,CALLBACK_ARGS:61,HREF:62,CSSCLASS:63,commentToken:64,textToken:65,graphCodeTokens:66,textNoTagsToken:67,TAGSTART:68,TAGEND:69,"==":70,"--":71,PCT:72,DEFAULT:73,SPACE:74,MINUS:75,keywords:76,UNICODE_TEXT:77,NUM:78,ALPHA:79,BQUOTE_STR:80,$accept:0,$end:1},terminals_:{2:"error",7:"direction_tb",8:"direction_bt",9:"direction_rl",10:"direction_lr",15:"NEWLINE",16:":",18:"open_directive",19:"type_directive",20:"arg_directive",21:"close_directive",22:"CLASS_DIAGRAM",24:"EOF",29:"GENERICTYPE",31:"LABEL",37:"CLASS",38:"STYLE_SEPARATOR",39:"STRUCT_START",41:"STRUCT_STOP",42:"ANNOTATION_START",43:"ANNOTATION_END",44:"MEMBER",45:"SEPARATOR",47:"STR",50:"AGGREGATION",51:"EXTENSION",52:"COMPOSITION",53:"DEPENDENCY",54:"LINE",55:"DOTTED_LINE",56:"CALLBACK",57:"LINK",58:"LINK_TARGET",59:"CLICK",60:"CALLBACK_NAME",61:"CALLBACK_ARGS",62:"HREF",63:"CSSCLASS",66:"graphCodeTokens",68:"TAGSTART",69:"TAGEND",70:"==",71:"--",72:"PCT",73:"DEFAULT",74:"SPACE",75:"MINUS",76:"keywords",77:"UNICODE_TEXT",78:"NUM",79:"ALPHA",80:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[3,2],[5,1],[5,1],[5,1],[5,1],[4,1],[6,4],[6,6],[12,1],[13,1],[17,1],[14,1],[11,4],[23,1],[23,2],[23,3],[26,1],[26,1],[26,2],[26,2],[26,2],[25,1],[25,2],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[32,2],[32,4],[32,5],[32,7],[34,4],[40,1],[40,2],[33,1],[33,2],[33,1],[33,1],[30,3],[30,4],[30,4],[30,5],[46,3],[46,2],[46,2],[46,1],[48,1],[48,1],[48,1],[48,1],[49,1],[49,1],[35,3],[35,4],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[36,3],[64,1],[64,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[67,1],[67,1],[67,1],[67,1],[27,1],[27,1],[27,1],[28,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setDirection("TB");break;case 5:r.setDirection("BT");break;case 6:r.setDirection("RL");break;case 7:r.setDirection("LR");break;case 11:r.parseDirective("%%{","open_directive");break;case 12:r.parseDirective(a[s],"type_directive");break;case 13:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 14:r.parseDirective("}%%","close_directive","class");break;case 19:case 20:this.$=a[s];break;case 21:this.$=a[s-1]+a[s];break;case 22:case 23:this.$=a[s-1]+"~"+a[s];break;case 24:r.addRelation(a[s]);break;case 25:a[s-1].title=r.cleanupLabel(a[s]),r.addRelation(a[s-1]);break;case 33:r.addClass(a[s]);break;case 34:r.addClass(a[s-2]),r.setCssClass(a[s-2],a[s]);break;case 35:r.addClass(a[s-3]),r.addMembers(a[s-3],a[s-1]);break;case 36:r.addClass(a[s-5]),r.setCssClass(a[s-5],a[s-3]),r.addMembers(a[s-5],a[s-1]);break;case 37:r.addAnnotation(a[s],a[s-2]);break;case 38:this.$=[a[s]];break;case 39:a[s].push(a[s-1]),this.$=a[s];break;case 40:case 42:case 43:break;case 41:r.addMember(a[s-1],r.cleanupLabel(a[s]));break;case 44:this.$={id1:a[s-2],id2:a[s],relation:a[s-1],relationTitle1:"none",relationTitle2:"none"};break;case 45:this.$={id1:a[s-3],id2:a[s],relation:a[s-1],relationTitle1:a[s-2],relationTitle2:"none"};break;case 46:this.$={id1:a[s-3],id2:a[s],relation:a[s-2],relationTitle1:"none",relationTitle2:a[s-1]};break;case 47:this.$={id1:a[s-4],id2:a[s],relation:a[s-2],relationTitle1:a[s-3],relationTitle2:a[s-1]};break;case 48:this.$={type1:a[s-2],type2:a[s],lineType:a[s-1]};break;case 49:this.$={type1:"none",type2:a[s],lineType:a[s-1]};break;case 50:this.$={type1:a[s-1],type2:"none",lineType:a[s]};break;case 51:this.$={type1:"none",type2:"none",lineType:a[s]};break;case 52:this.$=r.relationType.AGGREGATION;break;case 53:this.$=r.relationType.EXTENSION;break;case 54:this.$=r.relationType.COMPOSITION;break;case 55:this.$=r.relationType.DEPENDENCY;break;case 56:this.$=r.lineType.LINE;break;case 57:this.$=r.lineType.DOTTED_LINE;break;case 58:case 64:this.$=a[s-2],r.setClickEvent(a[s-1],a[s]);break;case 59:case 65:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 60:case 68:this.$=a[s-2],r.setLink(a[s-1],a[s]);break;case 61:case 69:this.$=a[s-3],r.setLink(a[s-2],a[s-1],a[s]);break;case 62:case 70:this.$=a[s-3],r.setLink(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 63:case 71:this.$=a[s-4],r.setLink(a[s-3],a[s-2],a[s]),r.setTooltip(a[s-3],a[s-1]);break;case 66:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 67:this.$=a[s-4],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setTooltip(a[s-3],a[s]);break;case 72:r.setCssClass(a[s-1],a[s])}},table:[{3:1,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[3]},{1:[2,1]},{1:[2,2]},{3:13,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[2,8]},t(s,[2,4]),t(s,[2,5]),t(s,[2,6]),t(s,[2,7]),{13:14,19:[1,15]},{15:[1,16]},{19:[2,11]},{1:[2,3]},{14:17,16:[1,18],21:c},t([16,21],[2,12]),{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:20,25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},{15:[1,45]},{17:46,20:[1,47]},{15:[2,14]},{24:[1,48]},{15:[1,49],24:[2,16]},t(x,[2,24],{31:[1,50]}),t(x,[2,26]),t(x,[2,27]),t(x,[2,28]),t(x,[2,29]),t(x,[2,30]),t(x,[2,31]),t(x,[2,32]),t(x,[2,40],{46:51,48:54,49:55,31:[1,53],47:[1,52],50:w,51:k,52:T,53:E,54:C,55:S}),{26:62,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,42]),t(x,[2,43]),{27:63,77:m,78:v,79:b},{26:64,27:39,28:40,77:m,78:v,79:b,80:_},{26:65,27:39,28:40,77:m,78:v,79:b,80:_},{26:66,27:39,28:40,77:m,78:v,79:b,80:_},{47:[1,67]},t(A,[2,19],{27:39,28:40,26:68,29:[1,69],77:m,78:v,79:b,80:_}),t(A,[2,20],{29:[1,70]}),t(M,[2,86]),t(M,[2,87]),t(M,[2,88]),t([15,24,29,31,38,39,47,50,51,52,53,54,55,60,62],[2,89]),t(N,[2,9]),{14:71,21:c},{21:[2,13]},{1:[2,15]},{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:72,24:[2,17],25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},t(x,[2,25]),{26:73,27:39,28:40,47:[1,74],77:m,78:v,79:b,80:_},{46:75,48:54,49:55,50:w,51:k,52:T,53:E,54:C,55:S},t(x,[2,41]),{49:76,54:C,55:S},t(D,[2,51],{48:77,50:w,51:k,52:T,53:E}),t(O,[2,52]),t(O,[2,53]),t(O,[2,54]),t(O,[2,55]),t(B,[2,56]),t(B,[2,57]),t(x,[2,33],{38:[1,78],39:[1,79]}),{43:[1,80]},{47:[1,81]},{47:[1,82]},{60:[1,83],62:[1,84]},{27:85,77:m,78:v,79:b},t(A,[2,21]),t(A,[2,22]),t(A,[2,23]),{15:[1,86]},{24:[2,18]},t(L,[2,44]),{26:87,27:39,28:40,77:m,78:v,79:b,80:_},{26:88,27:39,28:40,47:[1,89],77:m,78:v,79:b,80:_},t(D,[2,50],{48:90,50:w,51:k,52:T,53:E}),t(D,[2,49]),{27:91,77:m,78:v,79:b},{40:92,44:I},{26:94,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,58],{47:[1,95]}),t(x,[2,60],{47:[1,97],58:[1,96]}),t(x,[2,64],{47:[1,98],61:[1,99]}),t(x,[2,68],{47:[1,101],58:[1,100]}),t(x,[2,72]),t(N,[2,10]),t(L,[2,46]),t(L,[2,45]),{26:102,27:39,28:40,77:m,78:v,79:b,80:_},t(D,[2,48]),t(x,[2,34],{39:[1,103]}),{41:[1,104]},{40:105,41:[2,38],44:I},t(x,[2,37]),t(x,[2,59]),t(x,[2,61]),t(x,[2,62],{58:[1,106]}),t(x,[2,65]),t(x,[2,66],{47:[1,107]}),t(x,[2,69]),t(x,[2,70],{58:[1,108]}),t(L,[2,47]),{40:109,44:I},t(x,[2,35]),{41:[2,39]},t(x,[2,63]),t(x,[2,67]),t(x,[2,71]),{41:[1,110]},t(x,[2,36])],defaultActions:{2:[2,1],3:[2,2],5:[2,8],12:[2,11],13:[2,3],19:[2,14],47:[2,13],48:[2,15],72:[2,18],105:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},F={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),18;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 10;case 5:return this.begin("type_directive"),19;case 6:return this.popState(),this.begin("arg_directive"),16;case 7:return this.popState(),this.popState(),21;case 8:return 20;case 9:case 10:case 12:case 19:break;case 11:return 15;case 13:case 14:return 22;case 15:return this.begin("struct"),39;case 16:return"EOF_IN_STRUCT";case 17:return"OPEN_IN_STRUCT";case 18:return this.popState(),41;case 20:return"MEMBER";case 21:return 37;case 22:return 63;case 23:return 56;case 24:return 57;case 25:return 59;case 26:return 42;case 27:return 43;case 28:this.begin("generic");break;case 29:case 32:case 35:case 38:case 41:case 44:this.popState();break;case 30:return"GENERICTYPE";case 31:this.begin("string");break;case 33:return"STR";case 34:this.begin("bqstring");break;case 36:return"BQUOTE_STR";case 37:this.begin("href");break;case 39:return 62;case 40:this.begin("callback_name");break;case 42:this.popState(),this.begin("callback_args");break;case 43:return 60;case 45:return 61;case 46:case 47:case 48:case 49:return 58;case 50:case 51:return 51;case 52:case 53:return 53;case 54:return 52;case 55:return 50;case 56:return 54;case 57:return 55;case 58:return 31;case 59:return 38;case 60:return 75;case 61:return"DOT";case 62:return"PLUS";case 63:return 72;case 64:case 65:return"EQUALS";case 66:return 79;case 67:return"PUNCTUATION";case 68:return 78;case 69:return 77;case 70:return 74;case 71:return 24}},rules:[/^(?:%%\{)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:[{])/,/^(?:$)/,/^(?:[{])/,/^(?:[}])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:class\b)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:[~])/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[`])/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\s)/,/^(?:$)/],conditions:{arg_directive:{rules:[7,8],inclusive:!1},type_directive:{rules:[6,7],inclusive:!1},open_directive:{rules:[5],inclusive:!1},callback_args:{rules:[44,45],inclusive:!1},callback_name:{rules:[41,42,43],inclusive:!1},href:{rules:[38,39],inclusive:!1},struct:{rules:[16,17,18,19,20],inclusive:!1},generic:{rules:[29,30],inclusive:!1},bqstring:{rules:[35,36],inclusive:!1},string:{rules:[32,33],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,13,14,15,21,22,23,24,25,26,27,28,31,34,37,40,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71],inclusive:!0}}};function P(){this.yy={}}return R.lexer=F,P.prototype=R,R.Parser=P,new P}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8218).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},5890:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,23,41],i=[1,17],a=[1,20],o=[1,25],s=[1,26],c=[1,27],u=[1,28],l=[1,37],h=[23,38,39],f=[4,6,9,11,23,41],d=[34,35,36,37],p=[22,29],y=[1,55],g={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,entityName:17,relSpec:18,role:19,BLOCK_START:20,attributes:21,BLOCK_STOP:22,ALPHANUM:23,attribute:24,attributeType:25,attributeName:26,attributeKeyType:27,attributeComment:28,ATTRIBUTE_WORD:29,ATTRIBUTE_KEY:30,COMMENT:31,cardinality:32,relType:33,ZERO_OR_ONE:34,ZERO_OR_MORE:35,ONE_OR_MORE:36,ONLY_ONE:37,NON_IDENTIFYING:38,IDENTIFYING:39,WORD:40,open_directive:41,type_directive:42,arg_directive:43,close_directive:44,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",20:"BLOCK_START",22:"BLOCK_STOP",23:"ALPHANUM",29:"ATTRIBUTE_WORD",30:"ATTRIBUTE_KEY",31:"COMMENT",34:"ZERO_OR_ONE",35:"ZERO_OR_MORE",36:"ONE_OR_MORE",37:"ONLY_ONE",38:"NON_IDENTIFYING",39:"IDENTIFYING",40:"WORD",41:"open_directive",42:"type_directive",43:"arg_directive",44:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,5],[10,4],[10,3],[10,1],[17,1],[21,1],[21,2],[24,2],[24,3],[24,3],[24,4],[25,1],[26,1],[27,1],[28,1],[18,3],[32,1],[32,1],[32,1],[32,1],[33,1],[33,1],[19,1],[19,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:break;case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:case 16:case 23:case 24:case 25:case 35:this.$=a[s];break;case 12:r.addEntity(a[s-4]),r.addEntity(a[s-2]),r.addRelationship(a[s-4],a[s],a[s-2],a[s-3]);break;case 13:r.addEntity(a[s-3]),r.addAttributes(a[s-3],a[s-1]);break;case 14:r.addEntity(a[s-2]);break;case 15:r.addEntity(a[s]);break;case 17:this.$=[a[s]];break;case 18:a[s].push(a[s-1]),this.$=a[s];break;case 19:this.$={attributeType:a[s-1],attributeName:a[s]};break;case 20:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeKeyType:a[s]};break;case 21:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeComment:a[s]};break;case 22:this.$={attributeType:a[s-3],attributeName:a[s-2],attributeKeyType:a[s-1],attributeComment:a[s]};break;case 26:case 34:this.$=a[s].replace(/"/g,"");break;case 27:this.$={cardA:a[s],relType:a[s-1],cardB:a[s-2]};break;case 28:this.$=r.Cardinality.ZERO_OR_ONE;break;case 29:this.$=r.Cardinality.ZERO_OR_MORE;break;case 30:this.$=r.Cardinality.ONE_OR_MORE;break;case 31:this.$=r.Cardinality.ONLY_ONE;break;case 32:this.$=r.Identification.NON_IDENTIFYING;break;case 33:this.$=r.Identification.IDENTIFYING;break;case 36:r.parseDirective("%%{","open_directive");break;case 37:r.parseDirective(a[s],"type_directive");break;case 38:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 39:r.parseDirective("}%%","close_directive","er")}},table:[{3:1,4:e,7:3,12:4,41:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,41:n},{13:8,42:[1,9]},{42:[2,36]},{6:[1,10],7:15,8:11,9:[1,12],10:13,11:[1,14],12:4,17:16,23:i,41:n},{1:[2,2]},{14:18,15:[1,19],44:a},t([15,44],[2,37]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:15,10:21,12:4,17:16,23:i,41:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,15],{18:22,32:24,20:[1,23],34:o,35:s,36:c,37:u}),t([6,9,11,15,20,23,34,35,36,37,41],[2,16]),{11:[1,29]},{16:30,43:[1,31]},{11:[2,39]},t(r,[2,5]),{17:32,23:i},{21:33,22:[1,34],24:35,25:36,29:l},{33:38,38:[1,39],39:[1,40]},t(h,[2,28]),t(h,[2,29]),t(h,[2,30]),t(h,[2,31]),t(f,[2,9]),{14:41,44:a},{44:[2,38]},{15:[1,42]},{22:[1,43]},t(r,[2,14]),{21:44,22:[2,17],24:35,25:36,29:l},{26:45,29:[1,46]},{29:[2,23]},{32:47,34:o,35:s,36:c,37:u},t(d,[2,32]),t(d,[2,33]),{11:[1,48]},{19:49,23:[1,51],40:[1,50]},t(r,[2,13]),{22:[2,18]},t(p,[2,19],{27:52,28:53,30:[1,54],31:y}),t([22,29,30,31],[2,24]),{23:[2,27]},t(f,[2,10]),t(r,[2,12]),t(r,[2,34]),t(r,[2,35]),t(p,[2,20],{28:56,31:y}),t(p,[2,21]),t([22,29,31],[2,25]),t(p,[2,26]),t(p,[2,22])],defaultActions:{5:[2,36],7:[2,2],20:[2,39],31:[2,38],37:[2,23],44:[2,18],47:[2,27]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},m={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),41;case 1:return this.begin("type_directive"),42;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),44;case 4:return 43;case 5:case 6:case 8:case 13:case 17:break;case 7:return 11;case 9:return 9;case 10:return 40;case 11:return 4;case 12:return this.begin("block"),20;case 14:return 30;case 15:return 29;case 16:return 31;case 18:return this.popState(),22;case 19:case 32:return e.yytext[0];case 20:case 24:return 34;case 21:case 25:return 35;case 22:case 26:return 36;case 23:return 37;case 27:case 29:case 30:return 38;case 28:return 39;case 31:return 23;case 33:return 6}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:[\s]+)/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:\s+)/i,/^(?:(?:PK)|(?:FK))/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:\|o\b)/i,/^(?:\}o\b)/i,/^(?:\}\|)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:.)/i,/^(?:$)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},block:{rules:[13,14,15,16,17,18,19],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,20,21,22,23,24,25,26,27,28,29,30,31,32,33],inclusive:!0}}};function v(){this.yy={}}return g.lexer=m,v.prototype=g,g.Parser=v,new v}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8009).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3602:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,9],n=[1,7],r=[1,6],i=[1,8],a=[1,20,21,22,23,38,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],o=[2,10],s=[1,20],c=[1,21],u=[1,22],l=[1,23],h=[1,30],f=[1,59],d=[1,45],p=[1,49],y=[1,33],g=[1,34],m=[1,35],v=[1,36],b=[1,37],_=[1,53],x=[1,60],w=[1,48],k=[1,50],T=[1,52],E=[1,56],C=[1,57],S=[1,38],A=[1,39],M=[1,40],N=[1,41],D=[1,58],O=[1,47],B=[1,51],L=[1,54],I=[1,55],R=[1,46],F=[1,63],P=[1,68],j=[1,20,21,22,23,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],Y=[1,72],z=[1,71],U=[1,73],q=[20,21,23,74,75],H=[1,94],$=[1,99],W=[1,102],V=[1,103],G=[1,96],X=[1,101],Z=[1,104],Q=[1,97],K=[1,109],J=[1,108],tt=[1,98],et=[1,100],nt=[1,105],rt=[1,106],it=[1,107],at=[1,110],ot=[20,21,22,23,74,75],st=[20,21,22,23,48,74,75],ct=[20,21,22,23,40,47,48,50,52,54,56,58,59,60,62,64,66,67,69,74,75,84,88,98,99,102,104,105,115,116,117,118,119,120],ut=[20,21,23],lt=[20,21,23,47,59,60,74,75,84,88,98,99,102,104,105,115,116,117,118,119,120],ht=[1,12,20,21,22,23,24,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],ft=[47,59,60,84,88,98,99,102,104,105,115,116,117,118,119,120],dt=[1,143],pt=[1,151],yt=[1,152],gt=[1,153],mt=[1,154],vt=[1,138],bt=[1,139],_t=[1,135],xt=[1,146],wt=[1,147],kt=[1,148],Tt=[1,149],Et=[1,150],Ct=[1,155],St=[1,156],At=[1,141],Mt=[1,144],Nt=[1,140],Dt=[1,137],Ot=[20,21,22,23,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],Bt=[1,159],Lt=[20,21,22,23,26,47,59,60,84,98,99,102,104,105,115,116,117,118,119,120],It=[20,21,22,23,24,26,38,40,41,42,47,51,53,55,57,59,60,61,63,65,66,68,70,74,75,79,80,81,82,83,84,85,88,98,99,102,104,105,106,107,115,116,117,118,119,120],Rt=[12,21,22,24],Ft=[22,99],Pt=[1,242],jt=[1,237],Yt=[1,238],zt=[1,246],Ut=[1,243],qt=[1,240],Ht=[1,239],$t=[1,241],Wt=[1,244],Vt=[1,245],Gt=[1,247],Xt=[1,265],Zt=[20,21,23,99],Qt=[20,21,22,23,59,60,79,95,98,99,102,103,104,105,106],Kt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,directive:5,openDirective:6,typeDirective:7,closeDirective:8,separator:9,":":10,argDirective:11,open_directive:12,type_directive:13,arg_directive:14,close_directive:15,graphConfig:16,document:17,line:18,statement:19,SEMI:20,NEWLINE:21,SPACE:22,EOF:23,GRAPH:24,NODIR:25,DIR:26,FirstStmtSeperator:27,ending:28,endToken:29,spaceList:30,spaceListNewline:31,verticeStatement:32,styleStatement:33,linkStyleStatement:34,classDefStatement:35,classStatement:36,clickStatement:37,subgraph:38,text:39,SQS:40,SQE:41,end:42,direction:43,link:44,node:45,vertex:46,AMP:47,STYLE_SEPARATOR:48,idString:49,PS:50,PE:51,"(-":52,"-)":53,STADIUMSTART:54,STADIUMEND:55,SUBROUTINESTART:56,SUBROUTINEEND:57,VERTEX_WITH_PROPS_START:58,ALPHA:59,COLON:60,PIPE:61,CYLINDERSTART:62,CYLINDEREND:63,DIAMOND_START:64,DIAMOND_STOP:65,TAGEND:66,TRAPSTART:67,TRAPEND:68,INVTRAPSTART:69,INVTRAPEND:70,linkStatement:71,arrowText:72,TESTSTR:73,START_LINK:74,LINK:75,textToken:76,STR:77,keywords:78,STYLE:79,LINKSTYLE:80,CLASSDEF:81,CLASS:82,CLICK:83,DOWN:84,UP:85,textNoTags:86,textNoTagsToken:87,DEFAULT:88,stylesOpt:89,alphaNum:90,CALLBACKNAME:91,CALLBACKARGS:92,HREF:93,LINK_TARGET:94,HEX:95,numList:96,INTERPOLATE:97,NUM:98,COMMA:99,style:100,styleComponent:101,MINUS:102,UNIT:103,BRKT:104,DOT:105,PCT:106,TAGSTART:107,alphaNumToken:108,idStringToken:109,alphaNumStatement:110,direction_tb:111,direction_bt:112,direction_rl:113,direction_lr:114,PUNCTUATION:115,UNICODE_TEXT:116,PLUS:117,EQUALS:118,MULT:119,UNDERSCORE:120,graphCodeTokens:121,ARROW_CROSS:122,ARROW_POINT:123,ARROW_CIRCLE:124,ARROW_OPEN:125,QUOTE:126,$accept:0,$end:1},terminals_:{2:"error",10:":",12:"open_directive",13:"type_directive",14:"arg_directive",15:"close_directive",20:"SEMI",21:"NEWLINE",22:"SPACE",23:"EOF",24:"GRAPH",25:"NODIR",26:"DIR",38:"subgraph",40:"SQS",41:"SQE",42:"end",47:"AMP",48:"STYLE_SEPARATOR",50:"PS",51:"PE",52:"(-",53:"-)",54:"STADIUMSTART",55:"STADIUMEND",56:"SUBROUTINESTART",57:"SUBROUTINEEND",58:"VERTEX_WITH_PROPS_START",59:"ALPHA",60:"COLON",61:"PIPE",62:"CYLINDERSTART",63:"CYLINDEREND",64:"DIAMOND_START",65:"DIAMOND_STOP",66:"TAGEND",67:"TRAPSTART",68:"TRAPEND",69:"INVTRAPSTART",70:"INVTRAPEND",73:"TESTSTR",74:"START_LINK",75:"LINK",77:"STR",79:"STYLE",80:"LINKSTYLE",81:"CLASSDEF",82:"CLASS",83:"CLICK",84:"DOWN",85:"UP",88:"DEFAULT",91:"CALLBACKNAME",92:"CALLBACKARGS",93:"HREF",94:"LINK_TARGET",95:"HEX",97:"INTERPOLATE",98:"NUM",99:"COMMA",102:"MINUS",103:"UNIT",104:"BRKT",105:"DOT",106:"PCT",107:"TAGSTART",111:"direction_tb",112:"direction_bt",113:"direction_rl",114:"direction_lr",115:"PUNCTUATION",116:"UNICODE_TEXT",117:"PLUS",118:"EQUALS",119:"MULT",120:"UNDERSCORE",122:"ARROW_CROSS",123:"ARROW_POINT",124:"ARROW_CIRCLE",125:"ARROW_OPEN",126:"QUOTE"},productions_:[0,[3,1],[3,2],[5,4],[5,6],[6,1],[7,1],[11,1],[8,1],[4,2],[17,0],[17,2],[18,1],[18,1],[18,1],[18,1],[18,1],[16,2],[16,2],[16,2],[16,3],[28,2],[28,1],[29,1],[29,1],[29,1],[27,1],[27,1],[27,2],[31,2],[31,2],[31,1],[31,1],[30,2],[30,1],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,9],[19,6],[19,4],[19,1],[9,1],[9,1],[9,1],[32,3],[32,4],[32,2],[32,1],[45,1],[45,5],[45,3],[46,4],[46,6],[46,4],[46,4],[46,4],[46,8],[46,4],[46,4],[46,4],[46,6],[46,4],[46,4],[46,4],[46,4],[46,4],[46,1],[44,2],[44,3],[44,3],[44,1],[44,3],[71,1],[72,3],[39,1],[39,2],[39,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[86,1],[86,2],[35,5],[35,5],[36,5],[37,2],[37,4],[37,3],[37,5],[37,2],[37,4],[37,4],[37,6],[37,2],[37,4],[37,2],[37,4],[37,4],[37,6],[33,5],[33,5],[34,5],[34,5],[34,9],[34,9],[34,7],[34,7],[96,1],[96,3],[89,1],[89,3],[100,1],[100,2],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[76,1],[76,1],[76,1],[76,1],[76,1],[76,1],[87,1],[87,1],[87,1],[87,1],[49,1],[49,2],[90,1],[90,2],[110,1],[110,1],[110,1],[110,1],[43,1],[43,1],[43,1],[43,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 5:r.parseDirective("%%{","open_directive");break;case 6:r.parseDirective(a[s],"type_directive");break;case 7:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 8:r.parseDirective("}%%","close_directive","flowchart");break;case 10:case 36:case 37:case 38:case 39:case 40:this.$=[];break;case 11:a[s]!==[]&&a[s-1].push(a[s]),this.$=a[s-1];break;case 12:case 78:case 80:case 92:case 148:case 150:case 151:case 74:case 146:this.$=a[s];break;case 19:r.setDirection("TB"),this.$="TB";break;case 20:r.setDirection(a[s-1]),this.$=a[s-1];break;case 35:this.$=a[s-1].nodes;break;case 41:this.$=r.addSubGraph(a[s-6],a[s-1],a[s-4]);break;case 42:this.$=r.addSubGraph(a[s-3],a[s-1],a[s-3]);break;case 43:this.$=r.addSubGraph(void 0,a[s-1],void 0);break;case 48:r.addLink(a[s-2].stmt,a[s],a[s-1]),this.$={stmt:a[s],nodes:a[s].concat(a[s-2].nodes)};break;case 49:r.addLink(a[s-3].stmt,a[s-1],a[s-2]),this.$={stmt:a[s-1],nodes:a[s-1].concat(a[s-3].nodes)};break;case 50:this.$={stmt:a[s-1],nodes:a[s-1]};break;case 51:this.$={stmt:a[s],nodes:a[s]};break;case 52:case 119:case 121:this.$=[a[s]];break;case 53:this.$=a[s-4].concat(a[s]);break;case 54:this.$=[a[s-2]],r.setClass(a[s-2],a[s]);break;case 55:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"square");break;case 56:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"circle");break;case 57:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"ellipse");break;case 58:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"stadium");break;case 59:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"subroutine");break;case 60:this.$=a[s-7],r.addVertex(a[s-7],a[s-1],"rect",void 0,void 0,void 0,Object.fromEntries([[a[s-5],a[s-3]]]));break;case 61:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"cylinder");break;case 62:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"round");break;case 63:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"diamond");break;case 64:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"hexagon");break;case 65:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"odd");break;case 66:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"trapezoid");break;case 67:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"inv_trapezoid");break;case 68:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_right");break;case 69:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_left");break;case 70:this.$=a[s],r.addVertex(a[s]);break;case 71:a[s-1].text=a[s],this.$=a[s-1];break;case 72:case 73:a[s-2].text=a[s-1],this.$=a[s-2];break;case 75:var c=r.destructLink(a[s],a[s-2]);this.$={type:c.type,stroke:c.stroke,length:c.length,text:a[s-1]};break;case 76:c=r.destructLink(a[s]),this.$={type:c.type,stroke:c.stroke,length:c.length};break;case 77:this.$=a[s-1];break;case 79:case 93:case 149:case 147:this.$=a[s-1]+""+a[s];break;case 94:case 95:this.$=a[s-4],r.addClass(a[s-2],a[s]);break;case 96:this.$=a[s-4],r.setClass(a[s-2],a[s]);break;case 97:case 105:this.$=a[s-1],r.setClickEvent(a[s-1],a[s]);break;case 98:case 106:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 99:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 100:this.$=a[s-4],r.setClickEvent(a[s-4],a[s-3],a[s-2]),r.setTooltip(a[s-4],a[s]);break;case 101:case 107:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 102:case 108:this.$=a[s-3],r.setLink(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 103:case 109:this.$=a[s-3],r.setLink(a[s-3],a[s-2],a[s]);break;case 104:case 110:this.$=a[s-5],r.setLink(a[s-5],a[s-4],a[s]),r.setTooltip(a[s-5],a[s-2]);break;case 111:this.$=a[s-4],r.addVertex(a[s-2],void 0,void 0,a[s]);break;case 112:case 114:this.$=a[s-4],r.updateLink(a[s-2],a[s]);break;case 113:this.$=a[s-4],r.updateLink([a[s-2]],a[s]);break;case 115:this.$=a[s-8],r.updateLinkInterpolate([a[s-6]],a[s-2]),r.updateLink([a[s-6]],a[s]);break;case 116:this.$=a[s-8],r.updateLinkInterpolate(a[s-6],a[s-2]),r.updateLink(a[s-6],a[s]);break;case 117:this.$=a[s-6],r.updateLinkInterpolate([a[s-4]],a[s]);break;case 118:this.$=a[s-6],r.updateLinkInterpolate(a[s-4],a[s]);break;case 120:case 122:a[s-2].push(a[s]),this.$=a[s-2];break;case 124:this.$=a[s-1]+a[s];break;case 152:this.$="v";break;case 153:this.$="-";break;case 154:this.$={stmt:"dir",value:"TB"};break;case 155:this.$={stmt:"dir",value:"BT"};break;case 156:this.$={stmt:"dir",value:"RL"};break;case 157:this.$={stmt:"dir",value:"LR"}}},table:[{3:1,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},{1:[3]},{1:[2,1]},{3:10,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},t(a,o,{17:11}),{7:12,13:[1,13]},{16:14,21:n,22:r,24:i},{16:15,21:n,22:r,24:i},{25:[1,16],26:[1,17]},{13:[2,5]},{1:[2,2]},{1:[2,9],18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{8:61,10:[1,62],15:F},t([10,15],[2,6]),t(a,[2,17]),t(a,[2,18]),t(a,[2,19]),{20:[1,65],21:[1,66],22:P,27:64,30:67},t(j,[2,11]),t(j,[2,12]),t(j,[2,13]),t(j,[2,14]),t(j,[2,15]),t(j,[2,16]),{9:69,20:Y,21:z,23:U,44:70,71:74,74:[1,75],75:[1,76]},{9:77,20:Y,21:z,23:U},{9:78,20:Y,21:z,23:U},{9:79,20:Y,21:z,23:U},{9:80,20:Y,21:z,23:U},{9:81,20:Y,21:z,23:U},{9:83,20:Y,21:z,22:[1,82],23:U},t(j,[2,44]),t(q,[2,51],{30:84,22:P}),{22:[1,85]},{22:[1,86]},{22:[1,87]},{22:[1,88]},{26:H,47:$,59:W,60:V,77:[1,92],84:G,90:91,91:[1,89],93:[1,90],98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(j,[2,154]),t(j,[2,155]),t(j,[2,156]),t(j,[2,157]),t(ot,[2,52],{48:[1,111]}),t(st,[2,70],{109:123,40:[1,112],47:f,50:[1,113],52:[1,114],54:[1,115],56:[1,116],58:[1,117],59:d,60:p,62:[1,118],64:[1,119],66:[1,120],67:[1,121],69:[1,122],84:_,88:x,98:w,99:k,102:T,104:E,105:C,115:D,116:O,117:B,118:L,119:I,120:R}),t(ct,[2,146]),t(ct,[2,171]),t(ct,[2,172]),t(ct,[2,173]),t(ct,[2,174]),t(ct,[2,175]),t(ct,[2,176]),t(ct,[2,177]),t(ct,[2,178]),t(ct,[2,179]),t(ct,[2,180]),t(ct,[2,181]),t(ct,[2,182]),t(ct,[2,183]),t(ct,[2,184]),t(ct,[2,185]),t(ct,[2,186]),{9:124,20:Y,21:z,23:U},{11:125,14:[1,126]},t(ut,[2,8]),t(a,[2,20]),t(a,[2,26]),t(a,[2,27]),{21:[1,127]},t(lt,[2,34],{30:128,22:P}),t(j,[2,35]),{45:129,46:42,47:f,49:43,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},t(ht,[2,45]),t(ht,[2,46]),t(ht,[2,47]),t(ft,[2,74],{72:130,61:[1,132],73:[1,131]}),{22:dt,24:pt,26:yt,38:gt,39:133,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t([47,59,60,61,73,84,88,98,99,102,104,105,115,116,117,118,119,120],[2,76]),t(j,[2,36]),t(j,[2,37]),t(j,[2,38]),t(j,[2,39]),t(j,[2,40]),{22:dt,24:pt,26:yt,38:gt,39:157,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(Ot,o,{17:158}),t(q,[2,50],{47:Bt}),{26:H,47:$,59:W,60:V,84:G,90:160,95:[1,161],98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{88:[1,162],96:163,98:[1,164]},{26:H,47:$,59:W,60:V,84:G,88:[1,165],90:166,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{26:H,47:$,59:W,60:V,84:G,90:167,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,97],{22:[1,168],92:[1,169]}),t(ut,[2,101],{22:[1,170]}),t(ut,[2,105],{108:95,110:172,22:[1,171],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,107],{22:[1,173]}),t(Lt,[2,148]),t(Lt,[2,150]),t(Lt,[2,151]),t(Lt,[2,152]),t(Lt,[2,153]),t(It,[2,158]),t(It,[2,159]),t(It,[2,160]),t(It,[2,161]),t(It,[2,162]),t(It,[2,163]),t(It,[2,164]),t(It,[2,165]),t(It,[2,166]),t(It,[2,167]),t(It,[2,168]),t(It,[2,169]),t(It,[2,170]),{47:f,49:174,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},{22:dt,24:pt,26:yt,38:gt,39:175,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:177,42:mt,47:$,50:[1,176],59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:178,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:179,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:180,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{59:[1,181]},{22:dt,24:pt,26:yt,38:gt,39:182,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:183,42:mt,47:$,59:W,60:V,64:[1,184],66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:185,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:186,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:187,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ct,[2,147]),t(Rt,[2,3]),{8:188,15:F},{15:[2,7]},t(a,[2,28]),t(lt,[2,33]),t(q,[2,48],{30:189,22:P}),t(ft,[2,71],{22:[1,190]}),{22:[1,191]},{22:dt,24:pt,26:yt,38:gt,39:192,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,74:bt,75:[1,193],76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(It,[2,78]),t(It,[2,80]),t(It,[2,136]),t(It,[2,137]),t(It,[2,138]),t(It,[2,139]),t(It,[2,140]),t(It,[2,141]),t(It,[2,142]),t(It,[2,143]),t(It,[2,144]),t(It,[2,145]),t(It,[2,81]),t(It,[2,82]),t(It,[2,83]),t(It,[2,84]),t(It,[2,85]),t(It,[2,86]),t(It,[2,87]),t(It,[2,88]),t(It,[2,89]),t(It,[2,90]),t(It,[2,91]),{9:196,20:Y,21:z,22:dt,23:U,24:pt,26:yt,38:gt,40:[1,195],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,197],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{22:P,30:198},{22:[1,199],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:[1,200]},{22:[1,201]},{22:[1,202],99:[1,203]},t(Ft,[2,119]),{22:[1,204]},{22:[1,205],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:[1,206],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{77:[1,207]},t(ut,[2,99],{22:[1,208]}),{77:[1,209],94:[1,210]},{77:[1,211]},t(Lt,[2,149]),{77:[1,212],94:[1,213]},t(ot,[2,54],{109:123,47:f,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,115:D,116:O,117:B,118:L,119:I,120:R}),{22:dt,24:pt,26:yt,38:gt,41:[1,214],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:215,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,51:[1,216],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,53:[1,217],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,55:[1,218],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,57:[1,219],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{60:[1,220]},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,63:[1,221],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,65:[1,222],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:223,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,41:[1,224],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,68:[1,225],70:[1,226],74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,68:[1,228],70:[1,227],74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{9:229,20:Y,21:z,23:U},t(q,[2,49],{47:Bt}),t(ft,[2,73]),t(ft,[2,72]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,61:[1,230],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ft,[2,75]),t(It,[2,79]),{22:dt,24:pt,26:yt,38:gt,39:231,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(Ot,o,{17:232}),t(j,[2,43]),{46:233,47:f,49:43,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},{22:Pt,59:jt,60:Yt,79:zt,89:234,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:248,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:249,95:Ut,97:[1,250],98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:251,95:Ut,97:[1,252],98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{98:[1,253]},{22:Pt,59:jt,60:Yt,79:zt,89:254,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:255,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{26:H,47:$,59:W,60:V,84:G,90:256,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,98]),{77:[1,257]},t(ut,[2,102],{22:[1,258]}),t(ut,[2,103]),t(ut,[2,106]),t(ut,[2,108],{22:[1,259]}),t(ut,[2,109]),t(st,[2,55]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,51:[1,260],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,62]),t(st,[2,57]),t(st,[2,58]),t(st,[2,59]),{59:[1,261]},t(st,[2,61]),t(st,[2,63]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,65:[1,262],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,65]),t(st,[2,66]),t(st,[2,68]),t(st,[2,67]),t(st,[2,69]),t(Rt,[2,4]),t([22,47,59,60,84,88,98,99,102,104,105,115,116,117,118,119,120],[2,77]),{22:dt,24:pt,26:yt,38:gt,41:[1,263],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,264],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},t(ot,[2,53]),t(ut,[2,111],{99:Xt}),t(Zt,[2,121],{101:266,22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,102:Ht,103:$t,104:Wt,105:Vt,106:Gt}),t(Qt,[2,123]),t(Qt,[2,125]),t(Qt,[2,126]),t(Qt,[2,127]),t(Qt,[2,128]),t(Qt,[2,129]),t(Qt,[2,130]),t(Qt,[2,131]),t(Qt,[2,132]),t(Qt,[2,133]),t(Qt,[2,134]),t(Qt,[2,135]),t(ut,[2,112],{99:Xt}),t(ut,[2,113],{99:Xt}),{22:[1,267]},t(ut,[2,114],{99:Xt}),{22:[1,268]},t(Ft,[2,120]),t(ut,[2,94],{99:Xt}),t(ut,[2,95],{99:Xt}),t(ut,[2,96],{108:95,110:172,26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,100]),{94:[1,269]},{94:[1,270]},{51:[1,271]},{61:[1,272]},{65:[1,273]},{9:274,20:Y,21:z,23:U},t(j,[2,42]),{22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,100:275,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},t(Qt,[2,124]),{26:H,47:$,59:W,60:V,84:G,90:276,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{26:H,47:$,59:W,60:V,84:G,90:277,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,104]),t(ut,[2,110]),t(st,[2,56]),{22:dt,24:pt,26:yt,38:gt,39:278,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,64]),t(Ot,o,{17:279}),t(Zt,[2,122],{101:266,22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,102:Ht,103:$t,104:Wt,105:Vt,106:Gt}),t(ut,[2,117],{108:95,110:172,22:[1,280],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,118],{108:95,110:172,22:[1,281],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),{22:dt,24:pt,26:yt,38:gt,41:[1,282],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,283],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{22:Pt,59:jt,60:Yt,79:zt,89:284,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:285,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},t(st,[2,60]),t(j,[2,41]),t(ut,[2,115],{99:Xt}),t(ut,[2,116],{99:Xt})],defaultActions:{2:[2,1],9:[2,5],10:[2,2],126:[2,7]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},Jt={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),12;case 1:return this.begin("type_directive"),13;case 2:return this.popState(),this.begin("arg_directive"),10;case 3:return this.popState(),this.popState(),15;case 4:return 14;case 5:case 6:break;case 7:this.begin("string");break;case 8:case 17:case 20:case 23:case 26:this.popState();break;case 9:return"STR";case 10:return 79;case 11:return 88;case 12:return 80;case 13:return 97;case 14:return 81;case 15:return 82;case 16:this.begin("href");break;case 18:return 93;case 19:this.begin("callbackname");break;case 21:this.popState(),this.begin("callbackargs");break;case 22:return 91;case 24:return 92;case 25:this.begin("click");break;case 27:return 83;case 28:case 29:return t.lex.firstGraph()&&this.begin("dir"),24;case 30:return 38;case 31:return 42;case 32:case 33:case 34:case 35:return 94;case 36:return this.popState(),25;case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:return this.popState(),26;case 47:return 111;case 48:return 112;case 49:return 113;case 50:return 114;case 51:return 98;case 52:return 104;case 53:return 48;case 54:return 60;case 55:return 47;case 56:return 20;case 57:return 99;case 58:return 119;case 59:case 60:case 61:return 75;case 62:case 63:case 64:return 74;case 65:return 52;case 66:return 53;case 67:return 54;case 68:return 55;case 69:return 56;case 70:return 57;case 71:return 58;case 72:return 62;case 73:return 63;case 74:return 102;case 75:return 105;case 76:return 120;case 77:return 117;case 78:return 106;case 79:case 80:return 118;case 81:return 107;case 82:return 66;case 83:return 85;case 84:return"SEP";case 85:return 84;case 86:return 59;case 87:return 68;case 88:return 67;case 89:return 70;case 90:return 69;case 91:return 115;case 92:return 116;case 93:return 61;case 94:return 50;case 95:return 51;case 96:return 40;case 97:return 41;case 98:return 64;case 99:return 65;case 100:return 126;case 101:return 21;case 102:return 22;case 103:return 23}},rules:[/^(?:%%\{)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)[^\n]*)/,/^(?:[^\}]%%[^\n]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStyle\b)/,/^(?:interpolate\b)/,/^(?:classDef\b)/,/^(?:class\b)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:click[\s]+)/,/^(?:[\s\n])/,/^(?:[^\s\n]*)/,/^(?:graph\b)/,/^(?:flowchart\b)/,/^(?:subgraph\b)/,/^(?:end\b\s*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:(\r?\n)*\s*\n)/,/^(?:\s*LR\b)/,/^(?:\s*RL\b)/,/^(?:\s*TB\b)/,/^(?:\s*BT\b)/,/^(?:\s*TD\b)/,/^(?:\s*BR\b)/,/^(?:\s*<)/,/^(?:\s*>)/,/^(?:\s*\^)/,/^(?:\s*v\b)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:[0-9]+)/,/^(?:#)/,/^(?::::)/,/^(?::)/,/^(?:&)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\s*[xo<]?--+[-xo>]\s*)/,/^(?:\s*[xo<]?==+[=xo>]\s*)/,/^(?:\s*[xo<]?-?\.+-[xo>]?\s*)/,/^(?:\s*[xo<]?--\s*)/,/^(?:\s*[xo<]?==\s*)/,/^(?:\s*[xo<]?-\.\s*)/,/^(?:\(-)/,/^(?:-\))/,/^(?:\(\[)/,/^(?:\]\))/,/^(?:\[\[)/,/^(?:\]\])/,/^(?:\[\|)/,/^(?:\[\()/,/^(?:\)\])/,/^(?:-)/,/^(?:\.)/,/^(?:[\_])/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:<)/,/^(?:>)/,/^(?:\^)/,/^(?:\\\|)/,/^(?:v\b)/,/^(?:[A-Za-z]+)/,/^(?:\\\])/,/^(?:\[\/)/,/^(?:\/\])/,/^(?:\[\\)/,/^(?:[!"#$%&'*+,-.`?\\_/])/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\|)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:")/,/^(?:(\r?\n)+)/,/^(?:\s)/,/^(?:$)/],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[23,24],inclusive:!1},callbackname:{rules:[20,21,22],inclusive:!1},href:{rules:[17,18],inclusive:!1},click:{rules:[26,27],inclusive:!1},vertex:{rules:[],inclusive:!1},dir:{rules:[36,37,38,39,40,41,42,43,44,45,46],inclusive:!1},string:{rules:[8,9],inclusive:!1},INITIAL:{rules:[0,5,6,7,10,11,12,13,14,15,16,19,25,28,29,30,31,32,33,34,35,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103],inclusive:!0}}};function te(){this.yy={}}return Kt.lexer=Jt,te.prototype=Kt,Kt.Parser=te,new te}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(5354).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9959:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],i=[1,15],a=[1,16],o=[1,17],s=[1,18],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,23],d=[1,25],p=[1,27],y=[1,30],g=[5,7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],m={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,gantt:5,document:6,EOF:7,line:8,SPACE:9,statement:10,NL:11,dateFormat:12,inclusiveEndDates:13,topAxis:14,axisFormat:15,excludes:16,includes:17,todayMarker:18,title:19,section:20,clickStatement:21,taskTxt:22,taskData:23,openDirective:24,typeDirective:25,closeDirective:26,":":27,argDirective:28,click:29,callbackname:30,callbackargs:31,href:32,clickStatementDebug:33,open_directive:34,type_directive:35,arg_directive:36,close_directive:37,$accept:0,$end:1},terminals_:{2:"error",5:"gantt",7:"EOF",9:"SPACE",11:"NL",12:"dateFormat",13:"inclusiveEndDates",14:"topAxis",15:"axisFormat",16:"excludes",17:"includes",18:"todayMarker",19:"title",20:"section",22:"taskTxt",23:"taskData",27:":",29:"click",30:"callbackname",31:"callbackargs",32:"href",34:"open_directive",35:"type_directive",36:"arg_directive",37:"close_directive"},productions_:[0,[3,2],[3,3],[6,0],[6,2],[8,2],[8,1],[8,1],[8,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,1],[4,4],[4,6],[21,2],[21,3],[21,3],[21,4],[21,3],[21,4],[21,2],[33,2],[33,3],[33,3],[33,4],[33,3],[33,4],[33,2],[24,1],[25,1],[28,1],[26,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 2:return a[s-1];case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 9:r.setDateFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 10:r.enableInclusiveEndDates(),this.$=a[s].substr(18);break;case 11:r.TopAxis(),this.$=a[s].substr(8);break;case 12:r.setAxisFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 13:r.setExcludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 14:r.setIncludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 15:r.setTodayMarker(a[s].substr(12)),this.$=a[s].substr(12);break;case 16:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 17:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 19:r.addTask(a[s-1],a[s]),this.$="task";break;case 23:this.$=a[s-1],r.setClickEvent(a[s-1],a[s],null);break;case 24:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 25:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],null),r.setLink(a[s-2],a[s]);break;case 26:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setLink(a[s-3],a[s]);break;case 27:this.$=a[s-2],r.setClickEvent(a[s-2],a[s],null),r.setLink(a[s-2],a[s-1]);break;case 28:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-1],a[s]),r.setLink(a[s-3],a[s-2]);break;case 29:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 30:case 36:this.$=a[s-1]+" "+a[s];break;case 31:case 32:case 34:this.$=a[s-2]+" "+a[s-1]+" "+a[s];break;case 33:case 35:this.$=a[s-3]+" "+a[s-2]+" "+a[s-1]+" "+a[s];break;case 37:r.parseDirective("%%{","open_directive");break;case 38:r.parseDirective(a[s],"type_directive");break;case 39:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 40:r.parseDirective("}%%","close_directive","gantt")}},table:[{3:1,4:2,5:e,24:4,34:n},{1:[3]},{3:6,4:2,5:e,24:4,34:n},t(r,[2,3],{6:7}),{25:8,35:[1,9]},{35:[2,37]},{1:[2,1]},{4:26,7:[1,10],8:11,9:[1,12],10:13,11:[1,14],12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},{26:28,27:[1,29],37:y},t([27,37],[2,38]),t(r,[2,8],{1:[2,2]}),t(r,[2,4]),{4:26,10:31,12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,9]),t(r,[2,10]),t(r,[2,11]),t(r,[2,12]),t(r,[2,13]),t(r,[2,14]),t(r,[2,15]),t(r,[2,16]),t(r,[2,17]),t(r,[2,18]),{23:[1,32]},t(r,[2,20]),{30:[1,33],32:[1,34]},{11:[1,35]},{28:36,36:[1,37]},{11:[2,40]},t(r,[2,5]),t(r,[2,19]),t(r,[2,23],{31:[1,38],32:[1,39]}),t(r,[2,29],{30:[1,40]}),t(g,[2,21]),{26:41,37:y},{37:[2,39]},t(r,[2,24],{32:[1,42]}),t(r,[2,25]),t(r,[2,27],{31:[1,43]}),{11:[1,44]},t(r,[2,26]),t(r,[2,28]),t(g,[2,22])],defaultActions:{5:[2,37],6:[2,1],30:[2,40],37:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},v={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),34;case 1:return this.begin("type_directive"),35;case 2:return this.popState(),this.begin("arg_directive"),27;case 3:return this.popState(),this.popState(),37;case 4:return 36;case 5:case 6:case 7:case 9:case 10:case 11:break;case 8:return 11;case 12:this.begin("href");break;case 13:case 16:case 19:case 22:this.popState();break;case 14:return 32;case 15:this.begin("callbackname");break;case 17:this.popState(),this.begin("callbackargs");break;case 18:return 30;case 20:return 31;case 21:this.begin("click");break;case 23:return 29;case 24:return 5;case 25:return 12;case 26:return 13;case 27:return 14;case 28:return 15;case 29:return 17;case 30:return 16;case 31:return 18;case 32:return"date";case 33:return 19;case 34:return 20;case 35:return 22;case 36:return 23;case 37:return 27;case 38:return 7;case 39:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[19,20],inclusive:!1},callbackname:{rules:[16,17,18],inclusive:!1},href:{rules:[13,14],inclusive:!1},click:{rules:[22,23],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,15,21,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],inclusive:!0}}};function b(){this.yy={}}return m.lexer=v,b.prototype=m,m.Parser=b,new b}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(6878).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},2553:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[2,3],n=[1,7],r=[7,12,15,17,19,20,21],i=[7,11,12,15,17,19,20,21],a=[2,20],o=[1,32],s={trace:function(){},yy:{},symbols_:{error:2,start:3,GG:4,":":5,document:6,EOF:7,DIR:8,options:9,body:10,OPT:11,NL:12,line:13,statement:14,COMMIT:15,commit_arg:16,BRANCH:17,ID:18,CHECKOUT:19,MERGE:20,RESET:21,reset_arg:22,STR:23,HEAD:24,reset_parents:25,CARET:26,$accept:0,$end:1},terminals_:{2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD",26:"CARET"},productions_:[0,[3,4],[3,5],[6,0],[6,2],[9,2],[9,1],[10,0],[10,2],[13,2],[13,1],[14,2],[14,2],[14,2],[14,2],[14,2],[16,0],[16,1],[22,2],[22,2],[25,0],[25,2]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 2:return r.setDirection(a[s-3]),a[s-1];case 4:r.setOptions(a[s-1]),this.$=a[s];break;case 5:a[s-1]+=a[s],this.$=a[s-1];break;case 7:this.$=[];break;case 8:a[s-1].push(a[s]),this.$=a[s-1];break;case 9:this.$=a[s-1];break;case 11:r.commit(a[s]);break;case 12:r.branch(a[s]);break;case 13:r.checkout(a[s]);break;case 14:r.merge(a[s]);break;case 15:r.reset(a[s]);break;case 16:this.$="";break;case 17:this.$=a[s];break;case 18:this.$=a[s-1]+":"+a[s];break;case 19:this.$=a[s-1]+":"+r.count,r.count=0;break;case 20:r.count=0;break;case 21:r.count+=1}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3],8:[1,4]},{6:5,7:e,9:6,12:n},{5:[1,8]},{7:[1,9]},t(r,[2,7],{10:10,11:[1,11]}),t(i,[2,6]),{6:12,7:e,9:6,12:n},{1:[2,1]},{7:[2,4],12:[1,15],13:13,14:14,15:[1,16],17:[1,17],19:[1,18],20:[1,19],21:[1,20]},t(i,[2,5]),{7:[1,21]},t(r,[2,8]),{12:[1,22]},t(r,[2,10]),{12:[2,16],16:23,23:[1,24]},{18:[1,25]},{18:[1,26]},{18:[1,27]},{18:[1,30],22:28,24:[1,29]},{1:[2,2]},t(r,[2,9]),{12:[2,11]},{12:[2,17]},{12:[2,12]},{12:[2,13]},{12:[2,14]},{12:[2,15]},{12:a,25:31,26:o},{12:a,25:33,26:o},{12:[2,18]},{12:a,25:34,26:o},{12:[2,19]},{12:[2,21]}],defaultActions:{9:[2,1],21:[2,2],23:[2,11],24:[2,17],25:[2,12],26:[2,13],27:[2,14],28:[2,15],31:[2,18],33:[2,19],34:[2,21]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},c={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 12;case 1:case 2:case 3:break;case 4:return 4;case 5:return 15;case 6:return 17;case 7:return 20;case 8:return 21;case 9:return 19;case 10:case 11:return 8;case 12:return 5;case 13:return 26;case 14:this.begin("options");break;case 15:case 18:this.popState();break;case 16:return 11;case 17:this.begin("string");break;case 19:return 23;case 20:return 18;case 21:return 7}},rules:[/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit\b)/i,/^(?:branch\b)/i,/^(?:merge\b)/i,/^(?:reset\b)/i,/^(?:checkout\b)/i,/^(?:LR\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:end\r?\n)/i,/^(?:[^\n]+\r?\n)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[a-zA-Z][-_\.a-zA-Z0-9]*[-_a-zA-Z0-9])/i,/^(?:$)/i],conditions:{options:{rules:[15,16],inclusive:!1},string:{rules:[18,19],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,20,21],inclusive:!0}}};function u(){this.yy={}}return s.lexer=c,u.prototype=s,s.Parser=u,new u}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8183).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6765:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[6,9,10],n={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(t,e,n,r,i,a,o){switch(a.length,i){case 1:return r;case 4:break;case 6:r.setInfo(!0)}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},t(e,[2,3]),t(e,[2,4]),t(e,[2,5]),t(e,[2,6])],defaultActions:{4:[2,1]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},r={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 4;case 1:return 9;case 2:return"space";case 3:return 10;case 4:return 6;case 5:return"TXT"}},rules:[/^(?:info\b)/i,/^(?:[\s\n\r]+)/i,/^(?:[\s]+)/i,/^(?:showInfo\b)/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5],inclusive:!0}}};function i(){this.yy={}}return n.lexer=r,i.prototype=n,n.Parser=i,new i}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1428).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},7062:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,4],n=[1,5],r=[1,6],i=[1,7],a=[1,9],o=[1,11,13,20,21,22,23],s=[2,5],c=[1,6,11,13,20,21,22,23],u=[20,21,22],l=[2,8],h=[1,18],f=[1,19],d=[1,24],p=[6,20,21,22,23],y={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,directive:5,PIE:6,document:7,showData:8,line:9,statement:10,txt:11,value:12,title:13,title_value:14,openDirective:15,typeDirective:16,closeDirective:17,":":18,argDirective:19,NEWLINE:20,";":21,EOF:22,open_directive:23,type_directive:24,arg_directive:25,close_directive:26,$accept:0,$end:1},terminals_:{2:"error",6:"PIE",8:"showData",11:"txt",12:"value",13:"title",14:"title_value",18:":",20:"NEWLINE",21:";",22:"EOF",23:"open_directive",24:"type_directive",25:"arg_directive",26:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,3],[7,0],[7,2],[9,2],[10,0],[10,2],[10,2],[10,1],[5,3],[5,5],[4,1],[4,1],[4,1],[15,1],[16,1],[19,1],[17,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setShowData(!0);break;case 7:this.$=a[s-1];break;case 9:r.addSection(a[s-1],r.cleanupValue(a[s]));break;case 10:this.$=a[s].trim(),r.setTitle(this.$);break;case 17:r.parseDirective("%%{","open_directive");break;case 18:r.parseDirective(a[s],"type_directive");break;case 19:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 20:r.parseDirective("}%%","close_directive","pie")}},table:[{3:1,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{1:[3]},{3:10,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{3:11,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},t(o,s,{7:12,8:[1,13]}),t(c,[2,14]),t(c,[2,15]),t(c,[2,16]),{16:14,24:[1,15]},{24:[2,17]},{1:[2,1]},{1:[2,2]},t(u,l,{15:8,9:16,10:17,5:20,1:[2,3],11:h,13:f,23:a}),t(o,s,{7:21}),{17:22,18:[1,23],26:d},t([18,26],[2,18]),t(o,[2,6]),{4:25,20:n,21:r,22:i},{12:[1,26]},{14:[1,27]},t(u,[2,11]),t(u,l,{15:8,9:16,10:17,5:20,1:[2,4],11:h,13:f,23:a}),t(p,[2,12]),{19:28,25:[1,29]},t(p,[2,20]),t(o,[2,7]),t(u,[2,9]),t(u,[2,10]),{17:30,26:d},{26:[2,19]},t(p,[2,13])],defaultActions:{9:[2,17],10:[2,1],11:[2,2],29:[2,19]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},g={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),23;case 1:return this.begin("type_directive"),24;case 2:return this.popState(),this.begin("arg_directive"),18;case 3:return this.popState(),this.popState(),26;case 4:return 25;case 5:case 6:case 8:case 9:break;case 7:return 20;case 10:return this.begin("title"),13;case 11:return this.popState(),"title_value";case 12:this.begin("string");break;case 13:this.popState();break;case 14:return"txt";case 15:return 6;case 16:return 8;case 17:return"value";case 18:return 22}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},title:{rules:[11],inclusive:!1},string:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,12,15,16,17,18],inclusive:!0}}};function m(){this.yy={}}return y.lexer=g,m.prototype=y,y.Parser=m,new m}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(4551).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3176:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[1,17],i=[2,10],a=[1,21],o=[1,22],s=[1,23],c=[1,24],u=[1,25],l=[1,26],h=[1,19],f=[1,27],d=[1,28],p=[1,31],y=[66,67],g=[5,8,14,35,36,37,38,39,40,48,55,57,66,67],m=[5,6,8,14,35,36,37,38,39,40,48,66,67],v=[1,51],b=[1,52],_=[1,53],x=[1,54],w=[1,55],k=[1,56],T=[1,57],E=[57,58],C=[1,69],S=[1,65],A=[1,66],M=[1,67],N=[1,68],D=[1,70],O=[1,74],B=[1,75],L=[1,72],I=[1,73],R=[5,8,14,35,36,37,38,39,40,48,66,67],F={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,openDirective:9,typeDirective:10,closeDirective:11,":":12,argDirective:13,open_directive:14,type_directive:15,arg_directive:16,close_directive:17,requirementDef:18,elementDef:19,relationshipDef:20,requirementType:21,requirementName:22,STRUCT_START:23,requirementBody:24,ID:25,COLONSEP:26,id:27,TEXT:28,text:29,RISK:30,riskLevel:31,VERIFYMTHD:32,verifyType:33,STRUCT_STOP:34,REQUIREMENT:35,FUNCTIONAL_REQUIREMENT:36,INTERFACE_REQUIREMENT:37,PERFORMANCE_REQUIREMENT:38,PHYSICAL_REQUIREMENT:39,DESIGN_CONSTRAINT:40,LOW_RISK:41,MED_RISK:42,HIGH_RISK:43,VERIFY_ANALYSIS:44,VERIFY_DEMONSTRATION:45,VERIFY_INSPECTION:46,VERIFY_TEST:47,ELEMENT:48,elementName:49,elementBody:50,TYPE:51,type:52,DOCREF:53,ref:54,END_ARROW_L:55,relationship:56,LINE:57,END_ARROW_R:58,CONTAINS:59,COPIES:60,DERIVES:61,SATISFIES:62,VERIFIES:63,REFINES:64,TRACES:65,unqString:66,qString:67,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",12:":",14:"open_directive",15:"type_directive",16:"arg_directive",17:"close_directive",23:"STRUCT_START",25:"ID",26:"COLONSEP",28:"TEXT",30:"RISK",32:"VERIFYMTHD",34:"STRUCT_STOP",35:"REQUIREMENT",36:"FUNCTIONAL_REQUIREMENT",37:"INTERFACE_REQUIREMENT",38:"PERFORMANCE_REQUIREMENT",39:"PHYSICAL_REQUIREMENT",40:"DESIGN_CONSTRAINT",41:"LOW_RISK",42:"MED_RISK",43:"HIGH_RISK",44:"VERIFY_ANALYSIS",45:"VERIFY_DEMONSTRATION",46:"VERIFY_INSPECTION",47:"VERIFY_TEST",48:"ELEMENT",51:"TYPE",53:"DOCREF",55:"END_ARROW_L",57:"LINE",58:"END_ARROW_R",59:"CONTAINS",60:"COPIES",61:"DERIVES",62:"SATISFIES",63:"VERIFIES",64:"REFINES",65:"TRACES",66:"unqString",67:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,3],[4,5],[9,1],[10,1],[13,1],[11,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[18,5],[24,5],[24,5],[24,5],[24,5],[24,2],[24,1],[21,1],[21,1],[21,1],[21,1],[21,1],[21,1],[31,1],[31,1],[31,1],[33,1],[33,1],[33,1],[33,1],[19,5],[50,5],[50,5],[50,2],[50,1],[20,5],[20,5],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[22,1],[22,1],[27,1],[27,1],[29,1],[29,1],[49,1],[49,1],[52,1],[52,1],[54,1],[54,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 6:r.parseDirective("%%{","open_directive");break;case 7:r.parseDirective(a[s],"type_directive");break;case 8:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 9:r.parseDirective("}%%","close_directive","pie");break;case 10:this.$=[];break;case 16:r.addRequirement(a[s-3],a[s-4]);break;case 17:r.setNewReqId(a[s-2]);break;case 18:r.setNewReqText(a[s-2]);break;case 19:r.setNewReqRisk(a[s-2]);break;case 20:r.setNewReqVerifyMethod(a[s-2]);break;case 23:this.$=r.RequirementType.REQUIREMENT;break;case 24:this.$=r.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 25:this.$=r.RequirementType.INTERFACE_REQUIREMENT;break;case 26:this.$=r.RequirementType.PERFORMANCE_REQUIREMENT;break;case 27:this.$=r.RequirementType.PHYSICAL_REQUIREMENT;break;case 28:this.$=r.RequirementType.DESIGN_CONSTRAINT;break;case 29:this.$=r.RiskLevel.LOW_RISK;break;case 30:this.$=r.RiskLevel.MED_RISK;break;case 31:this.$=r.RiskLevel.HIGH_RISK;break;case 32:this.$=r.VerifyType.VERIFY_ANALYSIS;break;case 33:this.$=r.VerifyType.VERIFY_DEMONSTRATION;break;case 34:this.$=r.VerifyType.VERIFY_INSPECTION;break;case 35:this.$=r.VerifyType.VERIFY_TEST;break;case 36:r.addElement(a[s-3]);break;case 37:r.setNewElementType(a[s-2]);break;case 38:r.setNewElementDocRef(a[s-2]);break;case 41:r.addRelationship(a[s-2],a[s],a[s-4]);break;case 42:r.addRelationship(a[s-2],a[s-4],a[s]);break;case 43:this.$=r.Relationships.CONTAINS;break;case 44:this.$=r.Relationships.COPIES;break;case 45:this.$=r.Relationships.DERIVES;break;case 46:this.$=r.Relationships.SATISFIES;break;case 47:this.$=r.Relationships.VERIFIES;break;case 48:this.$=r.Relationships.REFINES;break;case 49:this.$=r.Relationships.TRACES}},table:[{3:1,4:2,6:e,9:4,14:n},{1:[3]},{3:7,4:2,5:[1,6],6:e,9:4,14:n},{5:[1,8]},{10:9,15:[1,10]},{15:[2,6]},{3:11,4:2,6:e,9:4,14:n},{1:[2,2]},{4:16,5:r,7:12,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{11:29,12:[1,30],17:p},t([12,17],[2,7]),{1:[2,1]},{8:[1,32]},{4:16,5:r,7:33,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:34,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:35,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:36,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:37,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{22:38,66:[1,39],67:[1,40]},{49:41,66:[1,42],67:[1,43]},{55:[1,44],57:[1,45]},t(y,[2,23]),t(y,[2,24]),t(y,[2,25]),t(y,[2,26]),t(y,[2,27]),t(y,[2,28]),t(g,[2,52]),t(g,[2,53]),t(m,[2,4]),{13:46,16:[1,47]},t(m,[2,9]),{1:[2,3]},{8:[2,11]},{8:[2,12]},{8:[2,13]},{8:[2,14]},{8:[2,15]},{23:[1,48]},{23:[2,50]},{23:[2,51]},{23:[1,49]},{23:[2,56]},{23:[2,57]},{56:50,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{56:58,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{11:59,17:p},{17:[2,8]},{5:[1,60]},{5:[1,61]},{57:[1,62]},t(E,[2,43]),t(E,[2,44]),t(E,[2,45]),t(E,[2,46]),t(E,[2,47]),t(E,[2,48]),t(E,[2,49]),{58:[1,63]},t(m,[2,5]),{5:C,24:64,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:71,51:L,53:I},{27:76,66:f,67:d},{27:77,66:f,67:d},t(R,[2,16]),{26:[1,78]},{26:[1,79]},{26:[1,80]},{26:[1,81]},{5:C,24:82,25:S,28:A,30:M,32:N,34:D},t(R,[2,22]),t(R,[2,36]),{26:[1,83]},{26:[1,84]},{5:O,34:B,50:85,51:L,53:I},t(R,[2,40]),t(R,[2,41]),t(R,[2,42]),{27:86,66:f,67:d},{29:87,66:[1,88],67:[1,89]},{31:90,41:[1,91],42:[1,92],43:[1,93]},{33:94,44:[1,95],45:[1,96],46:[1,97],47:[1,98]},t(R,[2,21]),{52:99,66:[1,100],67:[1,101]},{54:102,66:[1,103],67:[1,104]},t(R,[2,39]),{5:[1,105]},{5:[1,106]},{5:[2,54]},{5:[2,55]},{5:[1,107]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[1,108]},{5:[2,32]},{5:[2,33]},{5:[2,34]},{5:[2,35]},{5:[1,109]},{5:[2,58]},{5:[2,59]},{5:[1,110]},{5:[2,60]},{5:[2,61]},{5:C,24:111,25:S,28:A,30:M,32:N,34:D},{5:C,24:112,25:S,28:A,30:M,32:N,34:D},{5:C,24:113,25:S,28:A,30:M,32:N,34:D},{5:C,24:114,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:115,51:L,53:I},{5:O,34:B,50:116,51:L,53:I},t(R,[2,17]),t(R,[2,18]),t(R,[2,19]),t(R,[2,20]),t(R,[2,37]),t(R,[2,38])],defaultActions:{5:[2,6],7:[2,2],11:[2,1],32:[2,3],33:[2,11],34:[2,12],35:[2,13],36:[2,14],37:[2,15],39:[2,50],40:[2,51],42:[2,56],43:[2,57],47:[2,8],88:[2,54],89:[2,55],91:[2,29],92:[2,30],93:[2,31],95:[2,32],96:[2,33],97:[2,34],98:[2,35],100:[2,58],101:[2,59],103:[2,60],104:[2,61]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},P={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),14;case 1:return this.begin("type_directive"),15;case 2:return this.popState(),this.begin("arg_directive"),12;case 3:return this.popState(),this.popState(),17;case 4:return 16;case 5:return 5;case 6:case 7:case 8:break;case 9:return 8;case 10:return 6;case 11:return 23;case 12:return 34;case 13:return 26;case 14:return 25;case 15:return 28;case 16:return 30;case 17:return 32;case 18:return 35;case 19:return 36;case 20:return 37;case 21:return 38;case 22:return 39;case 23:return 40;case 24:return 41;case 25:return 42;case 26:return 43;case 27:return 44;case 28:return 45;case 29:return 46;case 30:return 47;case 31:return 48;case 32:return 59;case 33:return 60;case 34:return 61;case 35:return 62;case 36:return 63;case 37:return 64;case 38:return 65;case 39:return 51;case 40:return 53;case 41:return 55;case 42:return 58;case 43:return 57;case 44:this.begin("string");break;case 45:this.popState();break;case 46:return"qString";case 47:return e.yytext=e.yytext.trim(),66}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:$)/i,/^(?:requirementDiagram\b)/i,/^(?:\{)/i,/^(?:\})/i,/^(?::)/i,/^(?:id\b)/i,/^(?:text\b)/i,/^(?:risk\b)/i,/^(?:verifyMethod\b)/i,/^(?:requirement\b)/i,/^(?:functionalRequirement\b)/i,/^(?:interfaceRequirement\b)/i,/^(?:performanceRequirement\b)/i,/^(?:physicalRequirement\b)/i,/^(?:designConstraint\b)/i,/^(?:low\b)/i,/^(?:medium\b)/i,/^(?:high\b)/i,/^(?:analysis\b)/i,/^(?:demonstration\b)/i,/^(?:inspection\b)/i,/^(?:test\b)/i,/^(?:element\b)/i,/^(?:contains\b)/i,/^(?:copies\b)/i,/^(?:derives\b)/i,/^(?:satisfies\b)/i,/^(?:verifies\b)/i,/^(?:refines\b)/i,/^(?:traces\b)/i,/^(?:type\b)/i,/^(?:docref\b)/i,/^(?:<-)/i,/^(?:->)/i,/^(?:-)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[\w][^\r\n\{\<\>\-\=]*)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},unqString:{rules:[],inclusive:!1},token:{rules:[],inclusive:!1},string:{rules:[45,46],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,47],inclusive:!0}}};function j(){this.yy={}}return F.lexer=P,j.prototype=F,F.Parser=j,new j}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8800).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6876:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,18],u=[1,19],l=[1,21],h=[1,22],f=[1,23],d=[1,29],p=[1,30],y=[1,31],g=[1,32],m=[1,33],v=[1,34],b=[1,37],_=[1,38],x=[1,39],w=[1,40],k=[1,41],T=[1,42],E=[1,45],C=[1,4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],S=[1,58],A=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,42,46,47,48,49,57,67],M=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,41,42,46,47,48,49,57,67],N=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,42,46,47,48,49,57,67],D=[55,56,57],O=[1,4,5,7,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],B={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,directive:6,SD:7,document:8,line:9,statement:10,openDirective:11,typeDirective:12,closeDirective:13,":":14,argDirective:15,participant:16,actor:17,AS:18,restOfLine:19,participant_actor:20,signal:21,autonumber:22,activate:23,deactivate:24,note_statement:25,links_statement:26,link_statement:27,properties_statement:28,details_statement:29,title:30,text2:31,loop:32,end:33,rect:34,opt:35,alt:36,else_sections:37,par:38,par_sections:39,and:40,else:41,note:42,placement:43,over:44,actor_pair:45,links:46,link:47,properties:48,details:49,spaceList:50,",":51,left_of:52,right_of:53,signaltype:54,"+":55,"-":56,ACTOR:57,SOLID_OPEN_ARROW:58,DOTTED_OPEN_ARROW:59,SOLID_ARROW:60,DOTTED_ARROW:61,SOLID_CROSS:62,DOTTED_CROSS:63,SOLID_POINT:64,DOTTED_POINT:65,TXT:66,open_directive:67,type_directive:68,arg_directive:69,close_directive:70,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",7:"SD",14:":",16:"participant",18:"AS",19:"restOfLine",20:"participant_actor",22:"autonumber",23:"activate",24:"deactivate",30:"title",32:"loop",33:"end",34:"rect",35:"opt",36:"alt",38:"par",40:"and",41:"else",42:"note",44:"over",46:"links",47:"link",48:"properties",49:"details",51:",",52:"left_of",53:"right_of",55:"+",56:"-",57:"ACTOR",58:"SOLID_OPEN_ARROW",59:"DOTTED_OPEN_ARROW",60:"SOLID_ARROW",61:"DOTTED_ARROW",62:"SOLID_CROSS",63:"DOTTED_CROSS",64:"SOLID_POINT",65:"DOTTED_POINT",66:"TXT",67:"open_directive",68:"type_directive",69:"arg_directive",70:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[6,4],[6,6],[10,5],[10,3],[10,5],[10,3],[10,2],[10,1],[10,3],[10,3],[10,2],[10,2],[10,2],[10,2],[10,2],[10,3],[10,4],[10,4],[10,4],[10,4],[10,4],[10,1],[39,1],[39,4],[37,1],[37,4],[25,4],[25,4],[26,3],[27,3],[28,3],[29,3],[50,2],[50,1],[45,3],[45,1],[43,1],[43,1],[21,5],[21,5],[21,4],[17,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[31,1],[11,1],[12,1],[15,1],[13,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.apply(a[s]),a[s];case 5:case 9:this.$=[];break;case 6:a[s-1].push(a[s]),this.$=a[s-1];break;case 7:case 8:case 45:this.$=a[s];break;case 12:a[s-3].type="addParticipant",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 13:a[s-1].type="addParticipant",this.$=a[s-1];break;case 14:a[s-3].type="addActor",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 15:a[s-1].type="addActor",this.$=a[s-1];break;case 17:r.enableSequenceNumbers();break;case 18:this.$={type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]};break;case 19:this.$={type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-1]};break;case 25:this.$=[{type:"setTitle",text:a[s-1]}];break;case 26:a[s-1].unshift({type:"loopStart",loopText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.LOOP_START}),a[s-1].push({type:"loopEnd",loopText:a[s-2],signalType:r.LINETYPE.LOOP_END}),this.$=a[s-1];break;case 27:a[s-1].unshift({type:"rectStart",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_START}),a[s-1].push({type:"rectEnd",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_END}),this.$=a[s-1];break;case 28:a[s-1].unshift({type:"optStart",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_START}),a[s-1].push({type:"optEnd",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_END}),this.$=a[s-1];break;case 29:a[s-1].unshift({type:"altStart",altText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.ALT_START}),a[s-1].push({type:"altEnd",signalType:r.LINETYPE.ALT_END}),this.$=a[s-1];break;case 30:a[s-1].unshift({type:"parStart",parText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.PAR_START}),a[s-1].push({type:"parEnd",signalType:r.LINETYPE.PAR_END}),this.$=a[s-1];break;case 33:this.$=a[s-3].concat([{type:"and",parText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.PAR_AND},a[s]]);break;case 35:this.$=a[s-3].concat([{type:"else",altText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.ALT_ELSE},a[s]]);break;case 36:this.$=[a[s-1],{type:"addNote",placement:a[s-2],actor:a[s-1].actor,text:a[s]}];break;case 37:a[s-2]=[].concat(a[s-1],a[s-1]).slice(0,2),a[s-2][0]=a[s-2][0].actor,a[s-2][1]=a[s-2][1].actor,this.$=[a[s-1],{type:"addNote",placement:r.PLACEMENT.OVER,actor:a[s-2].slice(0,2),text:a[s]}];break;case 38:this.$=[a[s-1],{type:"addLinks",actor:a[s-1].actor,text:a[s]}];break;case 39:this.$=[a[s-1],{type:"addALink",actor:a[s-1].actor,text:a[s]}];break;case 40:this.$=[a[s-1],{type:"addProperties",actor:a[s-1].actor,text:a[s]}];break;case 41:this.$=[a[s-1],{type:"addDetails",actor:a[s-1].actor,text:a[s]}];break;case 44:this.$=[a[s-2],a[s]];break;case 46:this.$=r.PLACEMENT.LEFTOF;break;case 47:this.$=r.PLACEMENT.RIGHTOF;break;case 48:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]}];break;case 49:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-4]}];break;case 50:this.$=[a[s-3],a[s-1],{type:"addMessage",from:a[s-3].actor,to:a[s-1].actor,signalType:a[s-2],msg:a[s]}];break;case 51:this.$={type:"addParticipant",actor:a[s]};break;case 52:this.$=r.LINETYPE.SOLID_OPEN;break;case 53:this.$=r.LINETYPE.DOTTED_OPEN;break;case 54:this.$=r.LINETYPE.SOLID;break;case 55:this.$=r.LINETYPE.DOTTED;break;case 56:this.$=r.LINETYPE.SOLID_CROSS;break;case 57:this.$=r.LINETYPE.DOTTED_CROSS;break;case 58:this.$=r.LINETYPE.SOLID_POINT;break;case 59:this.$=r.LINETYPE.DOTTED_POINT;break;case 60:this.$=r.parseMessage(a[s].trim().substring(1));break;case 61:r.parseDirective("%%{","open_directive");break;case 62:r.parseDirective(a[s],"type_directive");break;case 63:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 64:r.parseDirective("}%%","close_directive","sequence")}},table:[{3:1,4:e,5:n,6:4,7:r,11:6,67:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,11:6,67:i},{3:9,4:e,5:n,6:4,7:r,11:6,67:i},{3:10,4:e,5:n,6:4,7:r,11:6,67:i},t([1,4,5,16,20,22,23,24,30,32,34,35,36,38,42,46,47,48,49,57,67],a,{8:11}),{12:12,68:[1,13]},{68:[2,61]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{13:43,14:[1,44],70:E},t([14,70],[2,62]),t(C,[2,6]),{6:35,10:46,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},t(C,[2,8]),t(C,[2,9]),{17:47,57:T},{17:48,57:T},{5:[1,49]},t(C,[2,17]),{17:50,57:T},{17:51,57:T},{5:[1,52]},{5:[1,53]},{5:[1,54]},{5:[1,55]},{5:[1,56]},{31:57,66:S},{19:[1,59]},{19:[1,60]},{19:[1,61]},{19:[1,62]},{19:[1,63]},t(C,[2,31]),{54:64,58:[1,65],59:[1,66],60:[1,67],61:[1,68],62:[1,69],63:[1,70],64:[1,71],65:[1,72]},{43:73,44:[1,74],52:[1,75],53:[1,76]},{17:77,57:T},{17:78,57:T},{17:79,57:T},{17:80,57:T},t([5,18,51,58,59,60,61,62,63,64,65,66],[2,51]),{5:[1,81]},{15:82,69:[1,83]},{5:[2,64]},t(C,[2,7]),{5:[1,85],18:[1,84]},{5:[1,87],18:[1,86]},t(C,[2,16]),{5:[1,88]},{5:[1,89]},t(C,[2,20]),t(C,[2,21]),t(C,[2,22]),t(C,[2,23]),t(C,[2,24]),{5:[1,90]},{5:[2,60]},t(A,a,{8:91}),t(A,a,{8:92}),t(A,a,{8:93}),t(M,a,{37:94,8:95}),t(N,a,{39:96,8:97}),{17:100,55:[1,98],56:[1,99],57:T},t(D,[2,52]),t(D,[2,53]),t(D,[2,54]),t(D,[2,55]),t(D,[2,56]),t(D,[2,57]),t(D,[2,58]),t(D,[2,59]),{17:101,57:T},{17:103,45:102,57:T},{57:[2,46]},{57:[2,47]},{31:104,66:S},{31:105,66:S},{31:106,66:S},{31:107,66:S},t(O,[2,10]),{13:108,70:E},{70:[2,63]},{19:[1,109]},t(C,[2,13]),{19:[1,110]},t(C,[2,15]),t(C,[2,18]),t(C,[2,19]),t(C,[2,25]),{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,111],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,112],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,113],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,114]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,34],34:y,35:g,36:m,38:v,41:[1,115],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,116]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,32],34:y,35:g,36:m,38:v,40:[1,117],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{17:118,57:T},{17:119,57:T},{31:120,66:S},{31:121,66:S},{31:122,66:S},{51:[1,123],66:[2,45]},{5:[2,38]},{5:[2,39]},{5:[2,40]},{5:[2,41]},{5:[1,124]},{5:[1,125]},{5:[1,126]},t(C,[2,26]),t(C,[2,27]),t(C,[2,28]),t(C,[2,29]),{19:[1,127]},t(C,[2,30]),{19:[1,128]},{31:129,66:S},{31:130,66:S},{5:[2,50]},{5:[2,36]},{5:[2,37]},{17:131,57:T},t(O,[2,11]),t(C,[2,12]),t(C,[2,14]),t(M,a,{8:95,37:132}),t(N,a,{8:97,39:133}),{5:[2,48]},{5:[2,49]},{66:[2,44]},{33:[2,35]},{33:[2,33]}],defaultActions:{7:[2,61],8:[2,1],9:[2,2],10:[2,3],45:[2,64],58:[2,60],75:[2,46],76:[2,47],83:[2,63],104:[2,38],105:[2,39],106:[2,40],107:[2,41],120:[2,50],121:[2,36],122:[2,37],129:[2,48],130:[2,49],131:[2,44],132:[2,35],133:[2,33]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},L={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),67;case 1:return this.begin("type_directive"),68;case 2:return this.popState(),this.begin("arg_directive"),14;case 3:return this.popState(),this.popState(),70;case 4:return 69;case 5:case 39:case 52:return 5;case 6:case 7:case 8:case 9:case 10:break;case 11:return this.begin("ID"),16;case 12:return this.begin("ID"),20;case 13:return e.yytext=e.yytext.trim(),this.begin("ALIAS"),57;case 14:return this.popState(),this.popState(),this.begin("LINE"),18;case 15:return this.popState(),this.popState(),5;case 16:return this.begin("LINE"),32;case 17:return this.begin("LINE"),34;case 18:return this.begin("LINE"),35;case 19:return this.begin("LINE"),36;case 20:return this.begin("LINE"),41;case 21:return this.begin("LINE"),38;case 22:return this.begin("LINE"),40;case 23:return this.popState(),19;case 24:return 33;case 25:return 52;case 26:return 53;case 27:return 46;case 28:return 47;case 29:return 48;case 30:return 49;case 31:return 44;case 32:return 42;case 33:return this.begin("ID"),23;case 34:return this.begin("ID"),24;case 35:return 30;case 36:return 7;case 37:return 22;case 38:return 51;case 40:return e.yytext=e.yytext.trim(),57;case 41:return 60;case 42:return 61;case 43:return 58;case 44:return 59;case 45:return 62;case 46:return 63;case 47:return 64;case 48:return 65;case 49:return 66;case 50:return 55;case 51:return 56;case 53:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:participant\b)/i,/^(?:actor\b)/i,/^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:(?:[:]?(?:no)?wrap)?[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:links\b)/i,/^(?:link\b)/i,/^(?:properties\b)/i,/^(?:details\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\b)/i,/^(?:sequenceDiagram\b)/i,/^(?:autonumber\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+((?!(-x|--x|-\)|--\)))[\-]*[^\+\->:\n,;]+)*)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?:-[\)])/i,/^(?:--[\)])/i,/^(?::(?:(?:no)?wrap)?[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1,8],inclusive:!1},type_directive:{rules:[2,3,8],inclusive:!1},arg_directive:{rules:[3,4,8],inclusive:!1},ID:{rules:[7,8,13],inclusive:!1},ALIAS:{rules:[7,8,14,15],inclusive:!1},LINE:{rules:[7,8,23],inclusive:!1},INITIAL:{rules:[0,5,6,8,9,10,11,12,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53],inclusive:!0}}};function I(){this.yy={}}return B.lexer=L,I.prototype=B,B.Parser=I,new I}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1993).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3584:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,30],d=[1,23],p=[1,24],y=[1,25],g=[1,26],m=[1,27],v=[1,32],b=[1,33],_=[1,34],x=[1,35],w=[1,31],k=[1,38],T=[1,4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],E=[1,4,5,12,13,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],C=[1,4,5,7,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],S=[4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],A={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,directive:6,SD:7,document:8,line:9,statement:10,idStatement:11,DESCR:12,"--\x3e":13,HIDE_EMPTY:14,scale:15,WIDTH:16,COMPOSIT_STATE:17,STRUCT_START:18,STRUCT_STOP:19,STATE_DESCR:20,AS:21,ID:22,FORK:23,JOIN:24,CHOICE:25,CONCURRENT:26,note:27,notePosition:28,NOTE_TEXT:29,direction:30,openDirective:31,typeDirective:32,closeDirective:33,":":34,argDirective:35,direction_tb:36,direction_bt:37,direction_rl:38,direction_lr:39,eol:40,";":41,EDGE_STATE:42,left_of:43,right_of:44,open_directive:45,type_directive:46,arg_directive:47,close_directive:48,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",7:"SD",12:"DESCR",13:"--\x3e",14:"HIDE_EMPTY",15:"scale",16:"WIDTH",17:"COMPOSIT_STATE",18:"STRUCT_START",19:"STRUCT_STOP",20:"STATE_DESCR",21:"AS",22:"ID",23:"FORK",24:"JOIN",25:"CHOICE",26:"CONCURRENT",27:"note",29:"NOTE_TEXT",34:":",36:"direction_tb",37:"direction_bt",38:"direction_rl",39:"direction_lr",41:";",42:"EDGE_STATE",43:"left_of",44:"right_of",45:"open_directive",46:"type_directive",47:"arg_directive",48:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[10,1],[10,2],[10,3],[10,4],[10,1],[10,2],[10,1],[10,4],[10,3],[10,6],[10,1],[10,1],[10,1],[10,1],[10,4],[10,4],[10,1],[10,1],[6,3],[6,5],[30,1],[30,1],[30,1],[30,1],[40,1],[40,1],[11,1],[11,1],[28,1],[28,1],[31,1],[32,1],[35,1],[33,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.setRootDoc(a[s]),a[s];case 5:this.$=[];break;case 6:"nl"!=a[s]&&(a[s-1].push(a[s]),this.$=a[s-1]);break;case 7:case 8:case 36:case 37:this.$=a[s];break;case 9:this.$="nl";break;case 10:this.$={stmt:"state",id:a[s],type:"default",description:""};break;case 11:this.$={stmt:"state",id:a[s-1],type:"default",description:r.trimColon(a[s])};break;case 12:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-2],type:"default",description:""},state2:{stmt:"state",id:a[s],type:"default",description:""}};break;case 13:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-3],type:"default",description:""},state2:{stmt:"state",id:a[s-1],type:"default",description:""},description:a[s].substr(1).trim()};break;case 17:this.$={stmt:"state",id:a[s-3],type:"default",description:"",doc:a[s-1]};break;case 18:var c=a[s],u=a[s-2].trim();if(a[s].match(":")){var l=a[s].split(":");c=l[0],u=[u,l[1]]}this.$={stmt:"state",id:c,type:"default",description:u};break;case 19:this.$={stmt:"state",id:a[s-3],type:"default",description:a[s-5],doc:a[s-1]};break;case 20:this.$={stmt:"state",id:a[s],type:"fork"};break;case 21:this.$={stmt:"state",id:a[s],type:"join"};break;case 22:this.$={stmt:"state",id:a[s],type:"choice"};break;case 23:this.$={stmt:"state",id:r.getDividerId(),type:"divider"};break;case 24:this.$={stmt:"state",id:a[s-1].trim(),note:{position:a[s-2].trim(),text:a[s].trim()}};break;case 30:r.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 31:r.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 32:r.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 33:r.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 40:r.parseDirective("%%{","open_directive");break;case 41:r.parseDirective(a[s],"type_directive");break;case 42:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 43:r.parseDirective("}%%","close_directive","state")}},table:[{3:1,4:e,5:n,6:4,7:r,31:6,45:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,31:6,45:i},{3:9,4:e,5:n,6:4,7:r,31:6,45:i},{3:10,4:e,5:n,6:4,7:r,31:6,45:i},t([1,4,5,14,15,17,20,22,23,24,25,26,27,36,37,38,39,42,45],a,{8:11}),{32:12,46:[1,13]},{46:[2,40]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},{33:36,34:[1,37],48:k},t([34,48],[2,41]),t(T,[2,6]),{6:28,10:39,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,8]),t(T,[2,9]),t(T,[2,10],{12:[1,40],13:[1,41]}),t(T,[2,14]),{16:[1,42]},t(T,[2,16],{18:[1,43]}),{21:[1,44]},t(T,[2,20]),t(T,[2,21]),t(T,[2,22]),t(T,[2,23]),{28:45,29:[1,46],43:[1,47],44:[1,48]},t(T,[2,26]),t(T,[2,27]),t(E,[2,36]),t(E,[2,37]),t(T,[2,30]),t(T,[2,31]),t(T,[2,32]),t(T,[2,33]),t(C,[2,28]),{35:49,47:[1,50]},t(C,[2,43]),t(T,[2,7]),t(T,[2,11]),{11:51,22:f,42:w},t(T,[2,15]),t(S,a,{8:52}),{22:[1,53]},{22:[1,54]},{21:[1,55]},{22:[2,38]},{22:[2,39]},{33:56,48:k},{48:[2,42]},t(T,[2,12],{12:[1,57]}),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,58],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,18],{18:[1,59]}),{29:[1,60]},{22:[1,61]},t(C,[2,29]),t(T,[2,13]),t(T,[2,17]),t(S,a,{8:62}),t(T,[2,24]),t(T,[2,25]),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,63],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,19])],defaultActions:{7:[2,40],8:[2,1],9:[2,2],10:[2,3],47:[2,38],48:[2,39],50:[2,42]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},M={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:case 26:return 36;case 1:case 27:return 37;case 2:case 28:return 38;case 3:case 29:return 39;case 4:return this.begin("open_directive"),45;case 5:return this.begin("type_directive"),46;case 6:return this.popState(),this.begin("arg_directive"),34;case 7:return this.popState(),this.popState(),48;case 8:return 47;case 9:case 10:case 12:case 13:case 14:case 15:case 39:case 45:break;case 11:case 59:return 5;case 16:return this.pushState("SCALE"),15;case 17:return 16;case 18:case 33:case 36:this.popState();break;case 19:this.pushState("STATE");break;case 20:case 23:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),23;case 21:case 24:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),24;case 22:case 25:return this.popState(),e.yytext=e.yytext.slice(0,-10).trim(),25;case 30:this.begin("STATE_STRING");break;case 31:return this.popState(),this.pushState("STATE_ID"),"AS";case 32:case 47:return this.popState(),"ID";case 34:return"STATE_DESCR";case 35:return 17;case 37:return this.popState(),this.pushState("struct"),18;case 38:return this.popState(),19;case 40:return this.begin("NOTE"),27;case 41:return this.popState(),this.pushState("NOTE_ID"),43;case 42:return this.popState(),this.pushState("NOTE_ID"),44;case 43:this.popState(),this.pushState("FLOATING_NOTE");break;case 44:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 46:return"NOTE_TEXT";case 48:return this.popState(),this.pushState("NOTE_TEXT"),22;case 49:return this.popState(),e.yytext=e.yytext.substr(2).trim(),29;case 50:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),29;case 51:case 52:return 7;case 53:return 14;case 54:return 42;case 55:return 22;case 56:return e.yytext=e.yytext.trim(),12;case 57:return 13;case 58:return 26;case 60:return"INVALID"}},rules:[/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:["])/i,/^(?:\s*as\s+)/i,/^(?:[^\n\{]*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n\s\{]+)/i,/^(?:\n)/i,/^(?:\{)/i,/^(?:\})/i,/^(?:[\n])/i,/^(?:note\s+)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:")/i,/^(?:\s*as\s*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n]*)/i,/^(?:\s*[^:\n\s\-]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:[\s\S]*?end note\b)/i,/^(?:stateDiagram\s+)/i,/^(?:stateDiagram-v2\s+)/i,/^(?:hide empty description\b)/i,/^(?:\[\*\])/i,/^(?:[^:\n\s\-\{]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:-->)/i,/^(?:--)/i,/^(?:$)/i,/^(?:.)/i],conditions:{LINE:{rules:[13,14],inclusive:!1},close_directive:{rules:[13,14],inclusive:!1},arg_directive:{rules:[7,8,13,14],inclusive:!1},type_directive:{rules:[6,7,13,14],inclusive:!1},open_directive:{rules:[5,13,14],inclusive:!1},struct:{rules:[13,14,19,26,27,28,29,38,39,40,54,55,56,57,58],inclusive:!1},FLOATING_NOTE_ID:{rules:[47],inclusive:!1},FLOATING_NOTE:{rules:[44,45,46],inclusive:!1},NOTE_TEXT:{rules:[49,50],inclusive:!1},NOTE_ID:{rules:[48],inclusive:!1},NOTE:{rules:[41,42,43],inclusive:!1},SCALE:{rules:[17,18],inclusive:!1},ALIAS:{rules:[],inclusive:!1},STATE_ID:{rules:[32],inclusive:!1},STATE_STRING:{rules:[33,34],inclusive:!1},FORK_STATE:{rules:[],inclusive:!1},STATE:{rules:[13,14,20,21,22,23,24,25,30,31,35,36,37],inclusive:!1},ID:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,14,15,16,19,37,40,51,52,53,54,55,56,57,59,60],inclusive:!0}}};function N(){this.yy={}}return A.lexer=M,N.prototype=A,A.Parser=N,new N}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(3069).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9763:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,17,18,19,21],i=[1,15],a=[1,16],o=[1,17],s=[1,21],c=[4,6,9,11,17,18,19,21],u={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,title:17,section:18,taskName:19,taskData:20,open_directive:21,type_directive:22,arg_directive:23,close_directive:24,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",17:"title",18:"section",19:"taskName",20:"taskData",21:"open_directive",22:"type_directive",23:"arg_directive",24:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,1],[10,2],[10,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 11:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 12:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 13:r.addTask(a[s-1],a[s]),this.$="task";break;case 15:r.parseDirective("%%{","open_directive");break;case 16:r.parseDirective(a[s],"type_directive");break;case 17:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 18:r.parseDirective("}%%","close_directive","journey")}},table:[{3:1,4:e,7:3,12:4,21:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,21:n},{13:8,22:[1,9]},{22:[2,15]},{6:[1,10],7:18,8:11,9:[1,12],10:13,11:[1,14],12:4,17:i,18:a,19:o,21:n},{1:[2,2]},{14:19,15:[1,20],24:s},t([15,24],[2,16]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:18,10:22,12:4,17:i,18:a,19:o,21:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,12]),{20:[1,23]},t(r,[2,14]),{11:[1,24]},{16:25,23:[1,26]},{11:[2,18]},t(r,[2,5]),t(r,[2,13]),t(c,[2,9]),{14:27,24:s},{24:[2,17]},{11:[1,28]},t(c,[2,10])],defaultActions:{5:[2,15],7:[2,2],21:[2,18],26:[2,17]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},l={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),21;case 1:return this.begin("type_directive"),22;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),24;case 4:return 23;case 5:case 6:case 8:case 9:break;case 7:return 11;case 10:return 4;case 11:return 17;case 12:return 18;case 13:return 19;case 14:return 20;case 15:return 15;case 16:return 6;case 17:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:journey\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17],inclusive:!0}}};function h(){this.yy={}}return u.lexer=l,h.prototype=u,u.Parser=h,new h}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(9143).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9609:t=>{"use strict";var e=/^(%20|\s)*(javascript|data)/im,n=/[^\x20-\x7E]/gim,r=/^([^:]+):/gm,i=[".","/"];t.exports={sanitizeUrl:function(t){if(!t)return"about:blank";var a,o,s=t.replace(n,"").trim();return function(t){return i.indexOf(t[0])>-1}(s)?s:(o=s.match(r))?(a=o[0],e.test(a)?"about:blank":s):"about:blank"}}},3841:t=>{t.exports=function(t,e){return t.intersect(e)}},7458:(t,e,n)=>{"use strict";n.d(e,{default:()=>sE});var r=n(1941),i=n.n(r),a={debug:1,info:2,warn:3,error:4,fatal:5},o={debug:function(){},info:function(){},warn:function(){},error:function(){},fatal:function(){}},s=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"fatal";isNaN(t)&&(t=t.toLowerCase(),void 0!==a[t]&&(t=a[t])),o.trace=function(){},o.debug=function(){},o.info=function(){},o.warn=function(){},o.error=function(){},o.fatal=function(){},t<=a.fatal&&(o.fatal=console.error?console.error.bind(console,c("FATAL"),"color: orange"):console.log.bind(console,"",c("FATAL"))),t<=a.error&&(o.error=console.error?console.error.bind(console,c("ERROR"),"color: orange"):console.log.bind(console,"",c("ERROR"))),t<=a.warn&&(o.warn=console.warn?console.warn.bind(console,c("WARN"),"color: orange"):console.log.bind(console,"",c("WARN"))),t<=a.info&&(o.info=console.info?console.info.bind(console,c("INFO"),"color: lightblue"):console.log.bind(console,"",c("INFO"))),t<=a.debug&&(o.debug=console.debug?console.debug.bind(console,c("DEBUG"),"color: lightgreen"):console.log.bind(console,"",c("DEBUG")))},c=function(t){var e=i()().format("ss.SSS");return"%c".concat(e," : ").concat(t," : ")};function u(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n=i)&&(n=i)}return n}function l(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n>e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}function h(t){return t}var f=1e-6;function d(t){return"translate("+t+",0)"}function p(t){return"translate(0,"+t+")"}function y(t){return e=>+t(e)}function g(t,e){return e=Math.max(0,t.bandwidth()-2*e)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function m(){return!this.__axis}function v(t,e){var n=[],r=null,i=null,a=6,o=6,s=3,c="undefined"!=typeof window&&window.devicePixelRatio>1?0:.5,u=1===t||4===t?-1:1,l=4===t||2===t?"x":"y",v=1===t||3===t?d:p;function b(d){var p=null==r?e.ticks?e.ticks.apply(e,n):e.domain():r,b=null==i?e.tickFormat?e.tickFormat.apply(e,n):h:i,_=Math.max(a,0)+s,x=e.range(),w=+x[0]+c,k=+x[x.length-1]+c,T=(e.bandwidth?g:y)(e.copy(),c),E=d.selection?d.selection():d,C=E.selectAll(".domain").data([null]),S=E.selectAll(".tick").data(p,e).order(),A=S.exit(),M=S.enter().append("g").attr("class","tick"),N=S.select("line"),D=S.select("text");C=C.merge(C.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),S=S.merge(M),N=N.merge(M.append("line").attr("stroke","currentColor").attr(l+"2",u*a)),D=D.merge(M.append("text").attr("fill","currentColor").attr(l,u*_).attr("dy",1===t?"0em":3===t?"0.71em":"0.32em")),d!==E&&(C=C.transition(d),S=S.transition(d),N=N.transition(d),D=D.transition(d),A=A.transition(d).attr("opacity",f).attr("transform",(function(t){return isFinite(t=T(t))?v(t+c):this.getAttribute("transform")})),M.attr("opacity",f).attr("transform",(function(t){var e=this.parentNode.__axis;return v((e&&isFinite(e=e(t))?e:T(t))+c)}))),A.remove(),C.attr("d",4===t||2===t?o?"M"+u*o+","+w+"H"+c+"V"+k+"H"+u*o:"M"+c+","+w+"V"+k:o?"M"+w+","+u*o+"V"+c+"H"+k+"V"+u*o:"M"+w+","+c+"H"+k),S.attr("opacity",1).attr("transform",(function(t){return v(T(t)+c)})),N.attr(l+"2",u*a),D.attr(l,u*_).text(b),E.filter(m).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",2===t?"start":4===t?"end":"middle"),E.each((function(){this.__axis=T}))}return b.scale=function(t){return arguments.length?(e=t,b):e},b.ticks=function(){return n=Array.from(arguments),b},b.tickArguments=function(t){return arguments.length?(n=null==t?[]:Array.from(t),b):n.slice()},b.tickValues=function(t){return arguments.length?(r=null==t?null:Array.from(t),b):r&&r.slice()},b.tickFormat=function(t){return arguments.length?(i=t,b):i},b.tickSize=function(t){return arguments.length?(a=o=+t,b):a},b.tickSizeInner=function(t){return arguments.length?(a=+t,b):a},b.tickSizeOuter=function(t){return arguments.length?(o=+t,b):o},b.tickPadding=function(t){return arguments.length?(s=+t,b):s},b.offset=function(t){return arguments.length?(c=+t,b):c},b}function b(){}function _(t){return null==t?b:function(){return this.querySelector(t)}}function x(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function w(){return[]}function k(t){return null==t?w:function(){return this.querySelectorAll(t)}}function T(t){return function(){return this.matches(t)}}function E(t){return function(e){return e.matches(t)}}var C=Array.prototype.find;function S(){return this.firstElementChild}var A=Array.prototype.filter;function M(){return Array.from(this.children)}function N(t){return new Array(t.length)}function D(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function O(t){return function(){return t}}function B(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;se?1:t>=e?0:NaN}D.prototype={constructor:D,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var P="http://www.w3.org/1999/xhtml";const j={svg:"http://www.w3.org/2000/svg",xhtml:P,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Y(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),j.hasOwnProperty(e)?{space:j[e],local:t}:t}function z(t){return function(){this.removeAttribute(t)}}function U(t){return function(){this.removeAttributeNS(t.space,t.local)}}function q(t,e){return function(){this.setAttribute(t,e)}}function H(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function $(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function W(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function V(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function G(t){return function(){this.style.removeProperty(t)}}function X(t,e,n){return function(){this.style.setProperty(t,e,n)}}function Z(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Q(t,e){return t.style.getPropertyValue(e)||V(t).getComputedStyle(t,null).getPropertyValue(e)}function K(t){return function(){delete this[t]}}function J(t,e){return function(){this[t]=e}}function tt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function et(t){return t.trim().split(/^|\s+/)}function nt(t){return t.classList||new rt(t)}function rt(t){this._node=t,this._names=et(t.getAttribute("class")||"")}function it(t,e){for(var n=nt(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Et(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Nt=[null];function Dt(t,e){this._groups=t,this._parents=e}function Ot(){return new Dt([[document.documentElement]],Nt)}Dt.prototype=Ot.prototype={constructor:Dt,select:function(t){"function"!=typeof t&&(t=_(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=F);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?G:"function"==typeof e?Z:X)(t,e,null==n?"":n)):Q(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?K:"function"==typeof e?tt:J)(t,e)):this.node()[t]},classed:function(t,e){var n=et(t+"");if(arguments.length<2){for(var r=nt(this.node()),i=-1,a=n.length;++i{}};function It(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Pt(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--qt}()}finally{qt=0,function(){for(var t,e,n=zt,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:zt=e);Ut=t,re(r)}(),Vt=0}}function ne(){var t=Xt.now(),e=t-Wt;e>1e3&&(Gt-=e,Wt=t)}function re(t){qt||(Ht&&(Ht=clearTimeout(Ht)),t-Vt>24?(t<1/0&&(Ht=setTimeout(ee,t-Xt.now()-Gt)),$t&&($t=clearInterval($t))):($t||(Wt=Xt.now(),$t=setInterval(ne,1e3)),qt=1,Zt(ee)))}function ie(t,e,n){var r=new Jt;return e=null==e?0:+e,r.restart(n=>{r.stop(),t(n+e)},e,n),r}Jt.prototype=te.prototype={constructor:Jt,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Qt():+n)+(null==e?0:+e),this._next||Ut===this||(Ut?Ut._next=this:zt=this,Ut=this),this._call=t,this._time=n,re()},stop:function(){this._call&&(this._call=null,this._time=1/0,re())}};var ae=Yt("start","end","cancel","interrupt"),oe=[];function se(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return ie(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function ue(t,e){var n=le(t,e);if(n.state>3)throw new Error("too late; already running");return n}function le(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function he(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var fe,de=180/Math.PI,pe={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function ye(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:he(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:he(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:he(t,n)},{i:s-2,x:he(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?ze(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?ze(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Ne.exec(t))?new He(e[1],e[2],e[3],1):(e=De.exec(t))?new He(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Oe.exec(t))?ze(e[1],e[2],e[3],e[4]):(e=Be.exec(t))?ze(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Le.exec(t))?Ge(e[1],e[2]/100,e[3]/100,1):(e=Ie.exec(t))?Ge(e[1],e[2]/100,e[3]/100,e[4]):Re.hasOwnProperty(t)?Ye(Re[t]):"transparent"===t?new He(NaN,NaN,NaN,0):null}function Ye(t){return new He(t>>16&255,t>>8&255,255&t,1)}function ze(t,e,n,r){return r<=0&&(t=e=n=NaN),new He(t,e,n,r)}function Ue(t){return t instanceof Te||(t=je(t)),t?new He((t=t.rgb()).r,t.g,t.b,t.opacity):new He}function qe(t,e,n,r){return 1===arguments.length?Ue(t):new He(t,e,n,null==r?1:r)}function He(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function $e(){return"#"+Ve(this.r)+Ve(this.g)+Ve(this.b)}function We(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Ve(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function Ge(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Ze(t,e,n,r)}function Xe(t){if(t instanceof Ze)return new Ze(t.h,t.s,t.l,t.opacity);if(t instanceof Te||(t=je(t)),!t)return new Ze;if(t instanceof Ze)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new Ze(o,s,c,t.opacity)}function Ze(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Qe(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Ke(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}we(Te,je,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Fe,formatHex:Fe,formatHsl:function(){return Xe(this).formatHsl()},formatRgb:Pe,toString:Pe}),we(He,qe,ke(Te,{brighter:function(t){return t=null==t?Ee:Math.pow(Ee,t),new He(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new He(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:$e,formatHex:$e,formatRgb:We,toString:We})),we(Ze,(function(t,e,n,r){return 1===arguments.length?Xe(t):new Ze(t,e,n,null==r?1:r)}),ke(Te,{brighter:function(t){return t=null==t?Ee:Math.pow(Ee,t),new Ze(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Ze(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new He(Qe(t>=240?t-240:t+120,i,r),Qe(t,i,r),Qe(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const Je=t=>()=>t;function tn(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):Je(isNaN(t)?e:t)}const en=function t(e){var n=function(t){return 1==(t=+t)?tn:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Je(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=qe(t)).r,(e=qe(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=tn(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function nn(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:he(n,r)})),a=an.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?ce:ue;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var Tn=Bt.prototype.constructor;function En(t){return function(){this.style.removeProperty(t)}}function Cn(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Sn(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Cn(t,a,n)),r}return a._value=e,a}function An(t){return function(e){this.textContent=t.call(this,e)}}function Mn(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&An(r)),e}return r._value=t,r}var Nn=0;function Dn(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function On(){return++Nn}var Bn=Bt.prototype;Dn.prototype=function(t){return Bt().transition(t)}.prototype={constructor:Dn,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=_(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Bt.prototype.transition=function(t){var e,n;t instanceof Dn?(e=t._id,t=t._name):(e=On(),(n=Ln).time=Qt(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?ar(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?ar(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Gn.exec(t))?new cr(e[1],e[2],e[3],1):(e=Xn.exec(t))?new cr(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Zn.exec(t))?ar(e[1],e[2],e[3],e[4]):(e=Qn.exec(t))?ar(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Kn.exec(t))?fr(e[1],e[2]/100,e[3]/100,1):(e=Jn.exec(t))?fr(e[1],e[2]/100,e[3]/100,e[4]):tr.hasOwnProperty(t)?ir(tr[t]):"transparent"===t?new cr(NaN,NaN,NaN,0):null}function ir(t){return new cr(t>>16&255,t>>8&255,255&t,1)}function ar(t,e,n,r){return r<=0&&(t=e=n=NaN),new cr(t,e,n,r)}function or(t){return t instanceof Un||(t=rr(t)),t?new cr((t=t.rgb()).r,t.g,t.b,t.opacity):new cr}function sr(t,e,n,r){return 1===arguments.length?or(t):new cr(t,e,n,null==r?1:r)}function cr(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function ur(){return"#"+hr(this.r)+hr(this.g)+hr(this.b)}function lr(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function hr(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function fr(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new pr(t,e,n,r)}function dr(t){if(t instanceof pr)return new pr(t.h,t.s,t.l,t.opacity);if(t instanceof Un||(t=rr(t)),!t)return new pr;if(t instanceof pr)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new pr(o,s,c,t.opacity)}function pr(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function yr(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}Yn(Un,rr,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:er,formatHex:er,formatHsl:function(){return dr(this).formatHsl()},formatRgb:nr,toString:nr}),Yn(cr,sr,zn(Un,{brighter:function(t){return t=null==t?qn:Math.pow(qn,t),new cr(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new cr(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:ur,formatHex:ur,formatRgb:lr,toString:lr})),Yn(pr,(function(t,e,n,r){return 1===arguments.length?dr(t):new pr(t,e,n,null==r?1:r)}),zn(Un,{brighter:function(t){return t=null==t?qn:Math.pow(qn,t),new pr(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new pr(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new cr(yr(t>=240?t-240:t+120,i,r),yr(t,i,r),yr(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const gr=Math.PI/180,mr=180/Math.PI,vr=6/29*3*(6/29);function br(t){if(t instanceof _r)return new _r(t.l,t.a,t.b,t.opacity);if(t instanceof Sr)return Ar(t);t instanceof cr||(t=or(t));var e,n,r=Tr(t.r),i=Tr(t.g),a=Tr(t.b),o=xr((.2225045*r+.7168786*i+.0606169*a)/1);return r===i&&i===a?e=n=o:(e=xr((.4360747*r+.3850649*i+.1430804*a)/.96422),n=xr((.0139322*r+.0971045*i+.7141733*a)/.82521)),new _r(116*o-16,500*(e-o),200*(o-n),t.opacity)}function _r(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function xr(t){return t>.008856451679035631?Math.pow(t,1/3):t/vr+4/29}function wr(t){return t>6/29?t*t*t:vr*(t-4/29)}function kr(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Tr(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Er(t){if(t instanceof Sr)return new Sr(t.h,t.c,t.l,t.opacity);if(t instanceof _r||(t=br(t)),0===t.a&&0===t.b)return new Sr(NaN,0()=>t;function Nr(t,e){return function(n){return t+n*e}}function Dr(t,e){var n=e-t;return n?Nr(t,n):Mr(isNaN(t)?e:t)}function Or(t){return function(e,n){var r=t((e=Cr(e)).h,(n=Cr(n)).h),i=Dr(e.c,n.c),a=Dr(e.l,n.l),o=Dr(e.opacity,n.opacity);return function(t){return e.h=r(t),e.c=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const Br=Or((function(t,e){var n=e-t;return n?Nr(t,n>180||n<-180?n-360*Math.round(n/360):n):Mr(isNaN(t)?e:t)}));Or(Dr);var Lr=Math.sqrt(50),Ir=Math.sqrt(10),Rr=Math.sqrt(2);function Fr(t,e,n){var r=(e-t)/Math.max(0,n),i=Math.floor(Math.log(r)/Math.LN10),a=r/Math.pow(10,i);return i>=0?(a>=Lr?10:a>=Ir?5:a>=Rr?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=Lr?10:a>=Ir?5:a>=Rr?2:1)}function Pr(t,e,n){var r=Math.abs(e-t)/Math.max(0,n),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),a=r/i;return a>=Lr?i*=10:a>=Ir?i*=5:a>=Rr&&(i*=2),ee?1:t>=e?0:NaN}function Yr(t){let e=t,n=t,r=t;function i(t,e,i=0,a=t.length){if(i>>1;r(t[n],e)<0?i=n+1:a=n}while(it(e)-n,n=jr,r=(e,n)=>jr(t(e),n)),{left:i,center:function(t,n,r=0,a=t.length){const o=i(t,n,r,a-1);return o>r&&e(t[o-1],n)>-e(t[o],n)?o-1:o},right:function(t,e,i=0,a=t.length){if(i>>1;r(t[n],e)<=0?i=n+1:a=n}while(i>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?ui(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?ui(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Kr.exec(t))?new fi(e[1],e[2],e[3],1):(e=Jr.exec(t))?new fi(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=ti.exec(t))?ui(e[1],e[2],e[3],e[4]):(e=ei.exec(t))?ui(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=ni.exec(t))?gi(e[1],e[2]/100,e[3]/100,1):(e=ri.exec(t))?gi(e[1],e[2]/100,e[3]/100,e[4]):ii.hasOwnProperty(t)?ci(ii[t]):"transparent"===t?new fi(NaN,NaN,NaN,0):null}function ci(t){return new fi(t>>16&255,t>>8&255,255&t,1)}function ui(t,e,n,r){return r<=0&&(t=e=n=NaN),new fi(t,e,n,r)}function li(t){return t instanceof Wr||(t=si(t)),t?new fi((t=t.rgb()).r,t.g,t.b,t.opacity):new fi}function hi(t,e,n,r){return 1===arguments.length?li(t):new fi(t,e,n,null==r?1:r)}function fi(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function di(){return"#"+yi(this.r)+yi(this.g)+yi(this.b)}function pi(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function yi(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function gi(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new vi(t,e,n,r)}function mi(t){if(t instanceof vi)return new vi(t.h,t.s,t.l,t.opacity);if(t instanceof Wr||(t=si(t)),!t)return new vi;if(t instanceof vi)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new vi(o,s,c,t.opacity)}function vi(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function bi(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function _i(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}Hr(Wr,si,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:ai,formatHex:ai,formatHsl:function(){return mi(this).formatHsl()},formatRgb:oi,toString:oi}),Hr(fi,hi,$r(Wr,{brighter:function(t){return t=null==t?Vr:Math.pow(Vr,t),new fi(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new fi(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:di,formatHex:di,formatRgb:pi,toString:pi})),Hr(vi,(function(t,e,n,r){return 1===arguments.length?mi(t):new vi(t,e,n,null==r?1:r)}),$r(Wr,{brighter:function(t){return t=null==t?Vr:Math.pow(Vr,t),new vi(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new vi(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new fi(bi(t>=240?t-240:t+120,i,r),bi(t,i,r),bi(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const xi=t=>()=>t;function wi(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):xi(isNaN(t)?e:t)}const ki=function t(e){var n=function(t){return 1==(t=+t)?wi:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):xi(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=hi(t)).r,(e=hi(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=wi(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function Ti(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Si(n,r)})),a=Ni.lastIndex;return ae&&(n=t,t=e,e=n),u=function(n){return Math.max(t,Math.min(e,n))}),r=c>2?Yi:ji,i=a=null,h}function h(e){return null==e||isNaN(e=+e)?n:(i||(i=r(o.map(t),s,c)))(t(u(e)))}return h.invert=function(n){return u(e((a||(a=r(s,o.map(t),Si)))(n)))},h.domain=function(t){return arguments.length?(o=Array.from(t,Ii),l()):o.slice()},h.range=function(t){return arguments.length?(s=Array.from(t),l()):s.slice()},h.rangeRound=function(t){return s=Array.from(t),c=Li,l()},h.clamp=function(t){return arguments.length?(u=!!t||Fi,l()):u!==Fi},h.interpolate=function(t){return arguments.length?(c=t,l()):c},h.unknown=function(t){return arguments.length?(n=t,h):n},function(n,r){return t=n,e=r,l()}}()(Fi,Fi)}function qi(t,e){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(e).domain(t)}return this}var Hi,$i=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Wi(t){if(!(e=$i.exec(t)))throw new Error("invalid format: "+t);var e;return new Vi({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function Vi(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function Gi(t,e){if((n=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var n,r=t.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+t.slice(n+1)]}function Xi(t){return(t=Gi(Math.abs(t)))?t[1]:NaN}function Zi(t,e){var n=Gi(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Wi.prototype=Vi.prototype,Vi.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const Qi={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>Zi(100*t,e),r:Zi,s:function(t,e){var n=Gi(t,e);if(!n)return t+"";var r=n[0],i=n[1],a=i-(Hi=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,o=r.length;return a===o?r:a>o?r+new Array(a-o+1).join("0"):a>0?r.slice(0,a)+"."+r.slice(a):"0."+new Array(1-a).join("0")+Gi(t,Math.max(0,e+a-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function Ki(t){return t}var Ji,ta,ea,na=Array.prototype.map,ra=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function ia(t){var e=t.domain;return t.ticks=function(t){var n=e();return function(t,e,n){var r,i,a,o,s=-1;if(n=+n,(t=+t)==(e=+e)&&n>0)return[t];if((r=e0){let n=Math.round(t/o),r=Math.round(e/o);for(n*oe&&--r,a=new Array(i=r-n+1);++se&&--r,a=new Array(i=r-n+1);++s0;){if((i=Fr(c,u,n))===r)return a[o]=c,a[s]=u,e(a);if(i>0)c=Math.floor(c/i)*i,u=Math.ceil(u/i)*i;else{if(!(i<0))break;c=Math.ceil(c*i)/i,u=Math.floor(u*i)/i}r=i}return t},t}Ji=function(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?Ki:(e=na.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,a=[],o=0,s=e[0],c=0;i>0&&s>0&&(c+s+1>r&&(s=Math.max(1,r-c)),a.push(t.substring(i-=s,i+s)),!((c+=s+1)>r));)s=e[o=(o+1)%e.length];return a.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",a=void 0===t.currency?"":t.currency[1]+"",o=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?Ki:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(na.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",u=void 0===t.minus?"−":t.minus+"",l=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=Wi(t)).fill,n=t.align,h=t.sign,f=t.symbol,d=t.zero,p=t.width,y=t.comma,g=t.precision,m=t.trim,v=t.type;"n"===v?(y=!0,v="g"):Qi[v]||(void 0===g&&(g=12),m=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var b="$"===f?i:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?a:/[%p]/.test(v)?c:"",x=Qi[v],w=/[defgprs%]/.test(v);function k(t){var i,a,c,f=b,k=_;if("c"===v)k=x(t)+k,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?l:x(Math.abs(t),g),m&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),T&&0==+t&&"+"!==h&&(T=!1),f=(T?"("===h?h:u:"-"===h||"("===h?"":h)+f,k=("s"===v?ra[8+Hi/3]:"")+k+(T&&"("===h?")":""),w)for(i=-1,a=t.length;++i(c=t.charCodeAt(i))||c>57){k=(46===c?o+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}y&&!d&&(t=r(t,1/0));var E=f.length+t.length+k.length,C=E>1)+f+t+k+C.slice(E);break;default:t=C+f+t+k}return s(t)}return g=void 0===g?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,g)):Math.max(0,Math.min(20,g)),k.toString=function(){return t+""},k}return{format:h,formatPrefix:function(t,e){var n=h(((t=Wi(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Xi(e)/3))),i=Math.pow(10,-r),a=ra[8+r/3];return function(t){return n(i*t)+a}}}}({thousands:",",grouping:[3],currency:["$",""]}),ta=Ji.format,ea=Ji.formatPrefix;class aa extends Map{constructor(t,e=sa){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const[e,n]of t)this.set(e,n)}get(t){return super.get(oa(this,t))}has(t){return super.has(oa(this,t))}set(t,e){return super.set(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):(t.set(r,n),n)}(this,t),e)}delete(t){return super.delete(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)&&(n=t.get(r),t.delete(r)),n}(this,t))}}function oa({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):n}function sa(t){return null!==t&&"object"==typeof t?t.valueOf():t}Set;const ca=Symbol("implicit"),ua=1e3,la=6e4,ha=36e5,fa=864e5,da=6048e5,pa=31536e6;var ya=new Date,ga=new Date;function ma(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return ya.setTime(+e),ga.setTime(+r),t(ya),t(ga),Math.floor(n(ya,ga))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var va=ma((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t}));va.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?ma((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):va:null};const ba=va;va.range;var _a=ma((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+e*ua)}),(function(t,e){return(e-t)/ua}),(function(t){return t.getUTCSeconds()}));const xa=_a;_a.range;var wa=ma((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*ua)}),(function(t,e){t.setTime(+t+e*la)}),(function(t,e){return(e-t)/la}),(function(t){return t.getMinutes()}));const ka=wa;wa.range;var Ta=ma((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*ua-t.getMinutes()*la)}),(function(t,e){t.setTime(+t+e*ha)}),(function(t,e){return(e-t)/ha}),(function(t){return t.getHours()}));const Ea=Ta;Ta.range;var Ca=ma(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*la)/fa,t=>t.getDate()-1);const Sa=Ca;function Aa(t){return ma((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*la)/da}))}Ca.range;var Ma=Aa(0),Na=Aa(1),Da=Aa(2),Oa=Aa(3),Ba=Aa(4),La=Aa(5),Ia=Aa(6),Ra=(Ma.range,Na.range,Da.range,Oa.range,Ba.range,La.range,Ia.range,ma((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()})));const Fa=Ra;Ra.range;var Pa=ma((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Pa.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ma((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const ja=Pa;Pa.range;var Ya=ma((function(t){t.setUTCSeconds(0,0)}),(function(t,e){t.setTime(+t+e*la)}),(function(t,e){return(e-t)/la}),(function(t){return t.getUTCMinutes()}));const za=Ya;Ya.range;var Ua=ma((function(t){t.setUTCMinutes(0,0,0)}),(function(t,e){t.setTime(+t+e*ha)}),(function(t,e){return(e-t)/ha}),(function(t){return t.getUTCHours()}));const qa=Ua;Ua.range;var Ha=ma((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/fa}),(function(t){return t.getUTCDate()-1}));const $a=Ha;function Wa(t){return ma((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/da}))}Ha.range;var Va=Wa(0),Ga=Wa(1),Xa=Wa(2),Za=Wa(3),Qa=Wa(4),Ka=Wa(5),Ja=Wa(6),to=(Va.range,Ga.range,Xa.range,Za.range,Qa.range,Ka.range,Ja.range,ma((function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCMonth(t.getUTCMonth()+e)}),(function(t,e){return e.getUTCMonth()-t.getUTCMonth()+12*(e.getUTCFullYear()-t.getUTCFullYear())}),(function(t){return t.getUTCMonth()})));const eo=to;to.range;var no=ma((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));no.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ma((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const ro=no;function io(t,e,n,r,i,a){const o=[[xa,1,ua],[xa,5,5e3],[xa,15,15e3],[xa,30,3e4],[a,1,la],[a,5,3e5],[a,15,9e5],[a,30,18e5],[i,1,ha],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,fa],[r,2,1728e5],[n,1,da],[e,1,2592e6],[e,3,7776e6],[t,1,pa]];function s(e,n,r){const i=Math.abs(n-e)/r,a=Yr(([,,t])=>t).right(o,i);if(a===o.length)return t.every(Pr(e/pa,n/pa,r));if(0===a)return ba.every(Math.max(Pr(e,n,r),1));const[s,c]=o[i/o[a-1][2][t.toLowerCase(),e]))}function ko(t,e,n){var r=go.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function To(t,e,n){var r=go.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Eo(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Co(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function So(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Ao(t,e,n){var r=go.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Mo(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function No(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Do(t,e,n){var r=go.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function Oo(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Bo(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Lo(t,e,n){var r=go.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Io(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Ro(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Fo(t,e,n){var r=go.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Po(t,e,n){var r=go.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function jo(t,e,n){var r=go.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Yo(t,e,n){var r=mo.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function zo(t,e,n){var r=go.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Uo(t,e,n){var r=go.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function qo(t,e){return bo(t.getDate(),e,2)}function Ho(t,e){return bo(t.getHours(),e,2)}function $o(t,e){return bo(t.getHours()%12||12,e,2)}function Wo(t,e){return bo(1+Sa.count(ja(t),t),e,3)}function Vo(t,e){return bo(t.getMilliseconds(),e,3)}function Go(t,e){return Vo(t,e)+"000"}function Xo(t,e){return bo(t.getMonth()+1,e,2)}function Zo(t,e){return bo(t.getMinutes(),e,2)}function Qo(t,e){return bo(t.getSeconds(),e,2)}function Ko(t){var e=t.getDay();return 0===e?7:e}function Jo(t,e){return bo(Ma.count(ja(t)-1,t),e,2)}function ts(t){var e=t.getDay();return e>=4||0===e?Ba(t):Ba.ceil(t)}function es(t,e){return t=ts(t),bo(Ba.count(ja(t),t)+(4===ja(t).getDay()),e,2)}function ns(t){return t.getDay()}function rs(t,e){return bo(Na.count(ja(t)-1,t),e,2)}function is(t,e){return bo(t.getFullYear()%100,e,2)}function as(t,e){return bo((t=ts(t)).getFullYear()%100,e,2)}function os(t,e){return bo(t.getFullYear()%1e4,e,4)}function ss(t,e){var n=t.getDay();return bo((t=n>=4||0===n?Ba(t):Ba.ceil(t)).getFullYear()%1e4,e,4)}function cs(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+bo(e/60|0,"0",2)+bo(e%60,"0",2)}function us(t,e){return bo(t.getUTCDate(),e,2)}function ls(t,e){return bo(t.getUTCHours(),e,2)}function hs(t,e){return bo(t.getUTCHours()%12||12,e,2)}function fs(t,e){return bo(1+$a.count(ro(t),t),e,3)}function ds(t,e){return bo(t.getUTCMilliseconds(),e,3)}function ps(t,e){return ds(t,e)+"000"}function ys(t,e){return bo(t.getUTCMonth()+1,e,2)}function gs(t,e){return bo(t.getUTCMinutes(),e,2)}function ms(t,e){return bo(t.getUTCSeconds(),e,2)}function vs(t){var e=t.getUTCDay();return 0===e?7:e}function bs(t,e){return bo(Va.count(ro(t)-1,t),e,2)}function _s(t){var e=t.getUTCDay();return e>=4||0===e?Qa(t):Qa.ceil(t)}function xs(t,e){return t=_s(t),bo(Qa.count(ro(t),t)+(4===ro(t).getUTCDay()),e,2)}function ws(t){return t.getUTCDay()}function ks(t,e){return bo(Ga.count(ro(t)-1,t),e,2)}function Ts(t,e){return bo(t.getUTCFullYear()%100,e,2)}function Es(t,e){return bo((t=_s(t)).getUTCFullYear()%100,e,2)}function Cs(t,e){return bo(t.getUTCFullYear()%1e4,e,4)}function Ss(t,e){var n=t.getUTCDay();return bo((t=n>=4||0===n?Qa(t):Qa.ceil(t)).getUTCFullYear()%1e4,e,4)}function As(){return"+0000"}function Ms(){return"%"}function Ns(t){return+t}function Ds(t){return Math.floor(+t/1e3)}function Os(t){return new Date(t)}function Bs(t){return t instanceof Date?+t:+new Date(+t)}function Ls(t,e,n,r,i,a,o,s,c,u){var l=Ui(),h=l.invert,f=l.domain,d=u(".%L"),p=u(":%S"),y=u("%I:%M"),g=u("%I %p"),m=u("%a %d"),v=u("%b %d"),b=u("%B"),_=u("%Y");function x(t){return(c(t)=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:Ns,s:Ds,S:Qo,u:Ko,U:Jo,V:es,w:ns,W:rs,x:null,X:null,y:is,Y:os,Z:cs,"%":Ms},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:us,e:us,f:ps,g:Es,G:Ss,H:ls,I:hs,j:fs,L:ds,m:ys,M:gs,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:Ns,s:Ds,S:ms,u:vs,U:bs,V:xs,w:ws,W:ks,x:null,X:null,y:Ts,Y:Cs,Z:As,"%":Ms},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Bo,e:Bo,f:jo,g:Mo,G:Ao,H:Io,I:Io,j:Lo,L:Po,m:Oo,M:Ro,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:Do,Q:zo,s:Uo,S:Fo,u:To,U:Eo,V:Co,w:ko,W:So,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:Mo,Y:Ao,Z:No,"%":Yo};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=lo(ho(a.y,0,1))).getUTCDay(),r=i>4||0===i?Ga.ceil(r):Ga(r),r=$a.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=uo(ho(a.y,0,1))).getDay(),r=i>4||0===i?Na.ceil(r):Na(r),r=Sa.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?lo(ho(a.y,0,1)).getUTCDay():uo(ho(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,lo(a)):uo(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in yo?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),po=fo.format,fo.parse,fo.utcFormat,fo.utcParse;var Us=Array.prototype.find;function qs(){return this.firstElementChild}var Hs=Array.prototype.filter;function $s(){return Array.from(this.children)}function Ws(t){return new Array(t.length)}function Vs(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function Gs(t){return function(){return t}}function Xs(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;se?1:t>=e?0:NaN}Vs.prototype={constructor:Vs,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var tc="http://www.w3.org/1999/xhtml";const ec={svg:"http://www.w3.org/2000/svg",xhtml:tc,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function nc(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),ec.hasOwnProperty(e)?{space:ec[e],local:t}:t}function rc(t){return function(){this.removeAttribute(t)}}function ic(t){return function(){this.removeAttributeNS(t.space,t.local)}}function ac(t,e){return function(){this.setAttribute(t,e)}}function oc(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function sc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function cc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function uc(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function lc(t){return function(){this.style.removeProperty(t)}}function hc(t,e,n){return function(){this.style.setProperty(t,e,n)}}function fc(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function dc(t,e){return t.style.getPropertyValue(e)||uc(t).getComputedStyle(t,null).getPropertyValue(e)}function pc(t){return function(){delete this[t]}}function yc(t,e){return function(){this[t]=e}}function gc(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function mc(t){return t.trim().split(/^|\s+/)}function vc(t){return t.classList||new bc(t)}function bc(t){this._node=t,this._names=mc(t.getAttribute("class")||"")}function _c(t,e){for(var n=vc(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function zc(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Wc=[null];function Vc(t,e){this._groups=t,this._parents=e}function Gc(){return new Vc([[document.documentElement]],Wc)}Vc.prototype=Gc.prototype={constructor:Vc,select:function(t){"function"!=typeof t&&(t=Rs(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=Js);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?lc:"function"==typeof e?fc:hc)(t,e,null==n?"":n)):dc(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?pc:"function"==typeof e?gc:yc)(t,e)):this.node()[t]},classed:function(t,e){var n=mc(t+"");if(arguments.length<2){for(var r=vc(this.node()),i=-1,a=n.length;++itu)if(Math.abs(l*s-c*u)>tu&&i){var f=n-a,d=r-o,p=s*s+c*c,y=f*f+d*d,g=Math.sqrt(p),m=Math.sqrt(h),v=i*Math.tan((Kc-Math.acos((p+h-y)/(2*g*m)))/2),b=v/m,_=v/g;Math.abs(b-1)>tu&&(this._+="L"+(t+b*u)+","+(e+b*l)),this._+="A"+i+","+i+",0,0,"+ +(l*f>u*d)+","+(this._x1=t+_*s)+","+(this._y1=e+_*c)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,r,i,a){t=+t,e=+e,a=!!a;var o=(n=+n)*Math.cos(r),s=n*Math.sin(r),c=t+o,u=e+s,l=1^a,h=a?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+c+","+u:(Math.abs(this._x1-c)>tu||Math.abs(this._y1-u)>tu)&&(this._+="L"+c+","+u),n&&(h<0&&(h=h%Jc+Jc),h>eu?this._+="A"+n+","+n+",0,1,"+l+","+(t-o)+","+(e-s)+"A"+n+","+n+",0,1,"+l+","+(this._x1=c)+","+(this._y1=u):h>tu&&(this._+="A"+n+","+n+",0,"+ +(h>=Kc)+","+l+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};const iu=ru;function au(t){return function(){return t}}var ou=Math.abs,su=Math.atan2,cu=Math.cos,uu=Math.max,lu=Math.min,hu=Math.sin,fu=Math.sqrt,du=1e-12,pu=Math.PI,yu=pu/2,gu=2*pu;function mu(t){return t>1?0:t<-1?pu:Math.acos(t)}function vu(t){return t>=1?yu:t<=-1?-yu:Math.asin(t)}function bu(t){return t.innerRadius}function _u(t){return t.outerRadius}function xu(t){return t.startAngle}function wu(t){return t.endAngle}function ku(t){return t&&t.padAngle}function Tu(t,e,n,r,i,a,o,s){var c=n-t,u=r-e,l=o-i,h=s-a,f=h*c-l*u;if(!(f*fN*N+D*D&&(T=C,E=S),{cx:T,cy:E,x01:-l,y01:-h,x11:T*(i/x-1),y11:E*(i/x-1)}}function Cu(){var t=bu,e=_u,n=au(0),r=null,i=xu,a=wu,o=ku,s=null;function c(){var c,u,l=+t.apply(this,arguments),h=+e.apply(this,arguments),f=i.apply(this,arguments)-yu,d=a.apply(this,arguments)-yu,p=ou(d-f),y=d>f;if(s||(s=c=iu()),hdu)if(p>gu-du)s.moveTo(h*cu(f),h*hu(f)),s.arc(0,0,h,f,d,!y),l>du&&(s.moveTo(l*cu(d),l*hu(d)),s.arc(0,0,l,d,f,y));else{var g,m,v=f,b=d,_=f,x=d,w=p,k=p,T=o.apply(this,arguments)/2,E=T>du&&(r?+r.apply(this,arguments):fu(l*l+h*h)),C=lu(ou(h-l)/2,+n.apply(this,arguments)),S=C,A=C;if(E>du){var M=vu(E/l*hu(T)),N=vu(E/h*hu(T));(w-=2*M)>du?(_+=M*=y?1:-1,x-=M):(w=0,_=x=(f+d)/2),(k-=2*N)>du?(v+=N*=y?1:-1,b-=N):(k=0,v=b=(f+d)/2)}var D=h*cu(v),O=h*hu(v),B=l*cu(x),L=l*hu(x);if(C>du){var I,R=h*cu(b),F=h*hu(b),P=l*cu(_),j=l*hu(_);if(pdu?A>du?(g=Eu(P,j,D,O,h,A,y),m=Eu(R,F,B,L,h,A,y),s.moveTo(g.cx+g.x01,g.cy+g.y01),Adu&&w>du?S>du?(g=Eu(B,L,R,F,l,-S,y),m=Eu(D,O,P,j,l,-S,y),s.lineTo(g.cx+g.x01,g.cy+g.y01),St?1:e>=t?0:NaN}function Lu(t){return t}function Iu(){}function Ru(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function Fu(t){this._context=t}function Pu(t){return new Fu(t)}function ju(t){this._context=t}function Yu(t){this._context=t}function zu(t){this._context=t}function Uu(t){return t<0?-1:1}function qu(t,e,n){var r=t._x1-t._x0,i=e-t._x1,a=(t._y1-t._y0)/(r||i<0&&-0),o=(n-t._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Uu(a)+Uu(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function Hu(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function $u(t,e,n){var r=t._x0,i=t._y0,a=t._x1,o=t._y1,s=(a-r)/3;t._context.bezierCurveTo(r+s,i+s*e,a-s,o-s*n,a,o)}function Wu(t){this._context=t}function Vu(t){this._context=new Gu(t)}function Gu(t){this._context=t}function Xu(t){this._context=t}function Zu(t){var e,n,r=t.length-1,i=new Array(r),a=new Array(r),o=new Array(r);for(i[0]=0,a[0]=2,o[0]=t[0]+2*t[1],e=1;e=0;--e)i[e]=(o[e]-i[e+1])/a[e];for(a[r-1]=(t[r]+i[r-1])/2,e=0;e=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};var Ku=new Date,Ju=new Date;function tl(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return Ku.setTime(+e),Ju.setTime(+r),t(Ku),t(Ju),Math.floor(n(Ku,Ju))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}const el=6048e5;function nl(t){return tl((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/el}))}var rl=nl(0),il=nl(1),al=nl(2),ol=nl(3),sl=nl(4),cl=nl(5),ul=nl(6),ll=(rl.range,il.range,al.range,ol.range,sl.range,cl.range,ul.range,tl((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/864e5}),(function(t){return t.getUTCDate()-1})));const hl=ll;function fl(t){return tl((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/el}))}ll.range;var dl=fl(0),pl=fl(1),yl=fl(2),gl=fl(3),ml=fl(4),vl=fl(5),bl=fl(6),_l=(dl.range,pl.range,yl.range,gl.range,ml.range,vl.range,bl.range,tl(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/864e5,t=>t.getDate()-1));const xl=_l;_l.range;var wl=tl((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));wl.every=function(t){return isFinite(t=Math.floor(t))&&t>0?tl((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const kl=wl;wl.range;var Tl=tl((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));Tl.every=function(t){return isFinite(t=Math.floor(t))&&t>0?tl((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const El=Tl;function Cl(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Sl(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Al(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}Tl.range;var Ml,Nl,Dl={"-":"",_:" ",0:"0"},Ol=/^\s*\d+/,Bl=/^%/,Ll=/[\\^$*+?|[\]().{}]/g;function Il(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a[t.toLowerCase(),e]))}function jl(t,e,n){var r=Ol.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Yl(t,e,n){var r=Ol.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function zl(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Ul(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function ql(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Hl(t,e,n){var r=Ol.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function $l(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function Wl(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Vl(t,e,n){var r=Ol.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function Gl(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Xl(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Zl(t,e,n){var r=Ol.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Ql(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Kl(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Jl(t,e,n){var r=Ol.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function th(t,e,n){var r=Ol.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function eh(t,e,n){var r=Ol.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function nh(t,e,n){var r=Bl.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function rh(t,e,n){var r=Ol.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function ih(t,e,n){var r=Ol.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function ah(t,e){return Il(t.getDate(),e,2)}function oh(t,e){return Il(t.getHours(),e,2)}function sh(t,e){return Il(t.getHours()%12||12,e,2)}function ch(t,e){return Il(1+xl.count(kl(t),t),e,3)}function uh(t,e){return Il(t.getMilliseconds(),e,3)}function lh(t,e){return uh(t,e)+"000"}function hh(t,e){return Il(t.getMonth()+1,e,2)}function fh(t,e){return Il(t.getMinutes(),e,2)}function dh(t,e){return Il(t.getSeconds(),e,2)}function ph(t){var e=t.getDay();return 0===e?7:e}function yh(t,e){return Il(dl.count(kl(t)-1,t),e,2)}function gh(t){var e=t.getDay();return e>=4||0===e?ml(t):ml.ceil(t)}function mh(t,e){return t=gh(t),Il(ml.count(kl(t),t)+(4===kl(t).getDay()),e,2)}function vh(t){return t.getDay()}function bh(t,e){return Il(pl.count(kl(t)-1,t),e,2)}function _h(t,e){return Il(t.getFullYear()%100,e,2)}function xh(t,e){return Il((t=gh(t)).getFullYear()%100,e,2)}function wh(t,e){return Il(t.getFullYear()%1e4,e,4)}function kh(t,e){var n=t.getDay();return Il((t=n>=4||0===n?ml(t):ml.ceil(t)).getFullYear()%1e4,e,4)}function Th(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+Il(e/60|0,"0",2)+Il(e%60,"0",2)}function Eh(t,e){return Il(t.getUTCDate(),e,2)}function Ch(t,e){return Il(t.getUTCHours(),e,2)}function Sh(t,e){return Il(t.getUTCHours()%12||12,e,2)}function Ah(t,e){return Il(1+hl.count(El(t),t),e,3)}function Mh(t,e){return Il(t.getUTCMilliseconds(),e,3)}function Nh(t,e){return Mh(t,e)+"000"}function Dh(t,e){return Il(t.getUTCMonth()+1,e,2)}function Oh(t,e){return Il(t.getUTCMinutes(),e,2)}function Bh(t,e){return Il(t.getUTCSeconds(),e,2)}function Lh(t){var e=t.getUTCDay();return 0===e?7:e}function Ih(t,e){return Il(rl.count(El(t)-1,t),e,2)}function Rh(t){var e=t.getUTCDay();return e>=4||0===e?sl(t):sl.ceil(t)}function Fh(t,e){return t=Rh(t),Il(sl.count(El(t),t)+(4===El(t).getUTCDay()),e,2)}function Ph(t){return t.getUTCDay()}function jh(t,e){return Il(il.count(El(t)-1,t),e,2)}function Yh(t,e){return Il(t.getUTCFullYear()%100,e,2)}function zh(t,e){return Il((t=Rh(t)).getUTCFullYear()%100,e,2)}function Uh(t,e){return Il(t.getUTCFullYear()%1e4,e,4)}function qh(t,e){var n=t.getUTCDay();return Il((t=n>=4||0===n?sl(t):sl.ceil(t)).getUTCFullYear()%1e4,e,4)}function Hh(){return"+0000"}function $h(){return"%"}function Wh(t){return+t}function Vh(t){return Math.floor(+t/1e3)}Ml=function(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=Fl(i),l=Pl(i),h=Fl(a),f=Pl(a),d=Fl(o),p=Pl(o),y=Fl(s),g=Pl(s),m=Fl(c),v=Pl(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:ah,e:ah,f:lh,g:xh,G:kh,H:oh,I:sh,j:ch,L:uh,m:hh,M:fh,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:Wh,s:Vh,S:dh,u:ph,U:yh,V:mh,w:vh,W:bh,x:null,X:null,y:_h,Y:wh,Z:Th,"%":$h},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:Eh,e:Eh,f:Nh,g:zh,G:qh,H:Ch,I:Sh,j:Ah,L:Mh,m:Dh,M:Oh,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:Wh,s:Vh,S:Bh,u:Lh,U:Ih,V:Fh,w:Ph,W:jh,x:null,X:null,y:Yh,Y:Uh,Z:Hh,"%":$h},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Xl,e:Xl,f:eh,g:$l,G:Hl,H:Ql,I:Ql,j:Zl,L:th,m:Gl,M:Kl,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:Vl,Q:rh,s:ih,S:Jl,u:Yl,U:zl,V:Ul,w:jl,W:ql,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:$l,Y:Hl,Z:Wl,"%":nh};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=Sl(Al(a.y,0,1))).getUTCDay(),r=i>4||0===i?il.ceil(r):il(r),r=hl.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=Cl(Al(a.y,0,1))).getDay(),r=i>4||0===i?pl.ceil(r):pl(r),r=xl.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?Sl(Al(a.y,0,1)).getUTCDay():Cl(Al(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,Sl(a)):Cl(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in Dl?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),Nl=Ml.format,Ml.parse,Ml.utcFormat,Ml.utcParse;var Gh={value:()=>{}};function Xh(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Kh(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--rf}()}finally{rf=0,function(){for(var t,e,n=ef,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:ef=e);nf=t,vf(r)}(),cf=0}}function mf(){var t=lf.now(),e=t-sf;e>1e3&&(uf-=e,sf=t)}function vf(t){rf||(af&&(af=clearTimeout(af)),t-cf>24?(t<1/0&&(af=setTimeout(gf,t-lf.now()-uf)),of&&(of=clearInterval(of))):(of||(sf=lf.now(),of=setInterval(mf,1e3)),rf=1,hf(gf)))}function bf(t,e,n){var r=new pf;return e=null==e?0:+e,r.restart(n=>{r.stop(),t(n+e)},e,n),r}pf.prototype=yf.prototype={constructor:pf,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?ff():+n)+(null==e?0:+e),this._next||nf===this||(nf?nf._next=this:ef=this,nf=this),this._call=t,this._time=n,vf()},stop:function(){this._call&&(this._call=null,this._time=1/0,vf())}};var _f=tf("start","end","cancel","interrupt"),xf=[];function wf(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return bf(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function Tf(t,e){var n=Ef(t,e);if(n.state>3)throw new Error("too late; already running");return n}function Ef(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function Cf(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var Sf,Af=180/Math.PI,Mf={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Nf(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:Cf(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:Cf(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:Cf(t,n)},{i:s-2,x:Cf(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Cf(n,r)})),a=zf.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?kf:Tf;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var od=Xc.prototype.constructor;function sd(t){return function(){this.style.removeProperty(t)}}function cd(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function ud(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&cd(t,a,n)),r}return a._value=e,a}function ld(t){return function(e){this.textContent=t.call(this,e)}}function hd(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&ld(r)),e}return r._value=t,r}var fd=0;function dd(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function pd(){return++fd}var yd=Xc.prototype;dd.prototype=function(t){return Xc().transition(t)}.prototype={constructor:dd,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Rs(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Xc.prototype.transition=function(t){var e,n;t instanceof dd?(e=t._id,t=t._name):(e=pd(),(n=gd).time=ff(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;ae?1:t>=e?0:NaN}Nd.prototype={constructor:Nd,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var Fd="http://www.w3.org/1999/xhtml";const Pd={svg:"http://www.w3.org/2000/svg",xhtml:Fd,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function jd(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),Pd.hasOwnProperty(e)?{space:Pd[e],local:t}:t}function Yd(t){return function(){this.removeAttribute(t)}}function zd(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Ud(t,e){return function(){this.setAttribute(t,e)}}function qd(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function Hd(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function $d(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function Wd(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function Vd(t){return function(){this.style.removeProperty(t)}}function Gd(t,e,n){return function(){this.style.setProperty(t,e,n)}}function Xd(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Zd(t,e){return t.style.getPropertyValue(e)||Wd(t).getComputedStyle(t,null).getPropertyValue(e)}function Qd(t){return function(){delete this[t]}}function Kd(t,e){return function(){this[t]=e}}function Jd(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function tp(t){return t.trim().split(/^|\s+/)}function ep(t){return t.classList||new np(t)}function np(t){this._node=t,this._names=tp(t.getAttribute("class")||"")}function rp(t,e){for(var n=ep(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Tp(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Mp=[null];function Np(t,e){this._groups=t,this._parents=e}function Dp(){return new Np([[document.documentElement]],Mp)}Np.prototype=Dp.prototype={constructor:Np,select:function(t){"function"!=typeof t&&(t=bd(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=Rd);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?Vd:"function"==typeof e?Xd:Gd)(t,e,null==n?"":n)):Zd(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?Qd:"function"==typeof e?Jd:Kd)(t,e)):this.node()[t]},classed:function(t,e){var n=tp(t+"");if(arguments.length<2){for(var r=ep(this.node()),i=-1,a=n.length;++i{}};function Lp(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Fp(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--Up}()}finally{Up=0,function(){for(var t,e,n=Yp,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Yp=e);zp=t,ny(r)}(),Wp=0}}function ey(){var t=Gp.now(),e=t-$p;e>1e3&&(Vp-=e,$p=t)}function ny(t){Up||(qp&&(qp=clearTimeout(qp)),t-Wp>24?(t<1/0&&(qp=setTimeout(ty,t-Gp.now()-Vp)),Hp&&(Hp=clearInterval(Hp))):(Hp||($p=Gp.now(),Hp=setInterval(ey,1e3)),Up=1,Xp(ty)))}function ry(t,e,n){var r=new Kp;return e=null==e?0:+e,r.restart(n=>{r.stop(),t(n+e)},e,n),r}Kp.prototype=Jp.prototype={constructor:Kp,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Zp():+n)+(null==e?0:+e),this._next||zp===this||(zp?zp._next=this:Yp=this,zp=this),this._call=t,this._time=n,ny()},stop:function(){this._call&&(this._call=null,this._time=1/0,ny())}};var iy=jp("start","end","cancel","interrupt"),ay=[];function oy(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return ry(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function cy(t,e){var n=uy(t,e);if(n.state>3)throw new Error("too late; already running");return n}function uy(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function ly(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var hy,fy=180/Math.PI,dy={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function py(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:ly(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:ly(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:ly(t,n)},{i:s-2,x:ly(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Yy(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Yy(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=My.exec(t))?new qy(e[1],e[2],e[3],1):(e=Ny.exec(t))?new qy(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Dy.exec(t))?Yy(e[1],e[2],e[3],e[4]):(e=Oy.exec(t))?Yy(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=By.exec(t))?Vy(e[1],e[2]/100,e[3]/100,1):(e=Ly.exec(t))?Vy(e[1],e[2]/100,e[3]/100,e[4]):Iy.hasOwnProperty(t)?jy(Iy[t]):"transparent"===t?new qy(NaN,NaN,NaN,0):null}function jy(t){return new qy(t>>16&255,t>>8&255,255&t,1)}function Yy(t,e,n,r){return r<=0&&(t=e=n=NaN),new qy(t,e,n,r)}function zy(t){return t instanceof ky||(t=Py(t)),t?new qy((t=t.rgb()).r,t.g,t.b,t.opacity):new qy}function Uy(t,e,n,r){return 1===arguments.length?zy(t):new qy(t,e,n,null==r?1:r)}function qy(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Hy(){return"#"+Wy(this.r)+Wy(this.g)+Wy(this.b)}function $y(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Wy(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function Vy(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Xy(t,e,n,r)}function Gy(t){if(t instanceof Xy)return new Xy(t.h,t.s,t.l,t.opacity);if(t instanceof ky||(t=Py(t)),!t)return new Xy;if(t instanceof Xy)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new Xy(o,s,c,t.opacity)}function Xy(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Zy(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Qy(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}xy(ky,Py,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Ry,formatHex:Ry,formatHsl:function(){return Gy(this).formatHsl()},formatRgb:Fy,toString:Fy}),xy(qy,Uy,wy(ky,{brighter:function(t){return t=null==t?Ty:Math.pow(Ty,t),new qy(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new qy(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Hy,formatHex:Hy,formatRgb:$y,toString:$y})),xy(Xy,(function(t,e,n,r){return 1===arguments.length?Gy(t):new Xy(t,e,n,null==r?1:r)}),wy(ky,{brighter:function(t){return t=null==t?Ty:Math.pow(Ty,t),new Xy(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Xy(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new qy(Zy(t>=240?t-240:t+120,i,r),Zy(t,i,r),Zy(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const Ky=t=>()=>t;function Jy(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):Ky(isNaN(t)?e:t)}const tg=function t(e){var n=function(t){return 1==(t=+t)?Jy:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Ky(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=Uy(t)).r,(e=Uy(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=Jy(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function eg(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:ly(n,r)})),a=rg.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?sy:cy;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var wg=Op.prototype.constructor;function kg(t){return function(){this.style.removeProperty(t)}}function Tg(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Eg(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Tg(t,a,n)),r}return a._value=e,a}function Cg(t){return function(e){this.textContent=t.call(this,e)}}function Sg(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Cg(r)),e}return r._value=t,r}var Ag=0;function Mg(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Ng(){return++Ag}var Dg=Op.prototype;Mg.prototype=function(t){return Op().transition(t)}.prototype={constructor:Mg,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=bd(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Op.prototype.transition=function(t){var e,n;t instanceof Mg?(e=t._id,t=t._name):(e=Ng(),(n=Og).time=Zp(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a2||im(Qg)>3?"":" "}function sm(t,e){for(;--e&&tm()&&!(Qg<48||Qg>102||Qg>57&&Qg<65||Qg>70&&Qg<97););return rm(t,nm()+(e<6&&32==em()&&32==tm()))}function cm(t,e){for(;tm()&&t+Qg!==57&&(t+Qg!==84||47!==em()););return"/*"+rm(e,Zg-1)+"*"+Rg(47===t?t:tm())}function um(t){for(;!im(em());)tm();return rm(t,Zg)}function lm(t){return function(t){return Kg="",t}(function t(e,n,r,i,a,o,s,c,u){for(var l=0,h=0,f=s,d=0,p=0,y=0,g=1,m=1,v=1,b=0,_="",x=a,w=o,k=i,T=_;m;)switch(y=b,b=tm()){case 40:if(108!=y&&58==T.charCodeAt(f-1)){-1!=jg(T+=Pg(am(b),"&","&\f"),"&\f")&&(v=-1);break}case 34:case 39:case 91:T+=am(b);break;case 9:case 10:case 13:case 32:T+=om(y);break;case 92:T+=sm(nm()-1,7);continue;case 47:switch(em()){case 42:case 47:Hg(fm(cm(tm(),nm()),n,r),u);break;default:T+="/"}break;case 123*g:c[l++]=Ug(T)*v;case 125*g:case 59:case 0:switch(b){case 0:case 125:m=0;case 59+h:p>0&&Ug(T)-f&&Hg(p>32?dm(T+";",i,r,f-1):dm(Pg(T," ","")+";",i,r,f-2),u);break;case 59:T+=";";default:if(Hg(k=hm(T,n,r,l,h,a,c,_,x=[],w=[],f),o),123===b)if(0===h)t(T,n,k,k,x,o,f,c,w);else switch(d){case 100:case 109:case 115:t(e,k,k,i&&Hg(hm(e,k,k,0,0,a,c,_,a,x=[],f),w),a,w,f,c,i?x:w);break;default:t(T,k,k,k,[""],w,0,c,w)}}l=h=p=0,g=v=1,_=T="",f=s;break;case 58:f=1+Ug(T),p=y;default:if(g<1)if(123==b)--g;else if(125==b&&0==g++&&125==(Qg=Zg>0?Yg(Kg,--Zg):0,Gg--,10===Qg&&(Gg=1,Vg--),Qg))continue;switch(T+=Rg(b),b*g){case 38:v=h>0?1:(T+="\f",-1);break;case 44:c[l++]=(Ug(T)-1)*v,v=1;break;case 64:45===em()&&(T+=am(tm())),d=em(),h=f=Ug(_=T+=um(nm())),b++;break;case 45:45===y&&2==Ug(T)&&(g=0)}}return o}("",null,null,null,[""],t=function(t){return Vg=Gg=1,Xg=Ug(Kg=t),Zg=0,[]}(t),0,[0],t))}function hm(t,e,n,r,i,a,o,s,c,u,l){for(var h=i-1,f=0===i?a:[""],d=qg(f),p=0,y=0,g=0;p0?f[m]+" "+v:Pg(v,/&\f/g,f[m])))&&(c[g++]=b);return Jg(t,e,n,0===i?"rule":s,c,u,l)}function fm(t,e,n){return Jg(t,e,n,"comm",Rg(Qg),zg(t,2,-2),0)}function dm(t,e,n,r){return Jg(t,e,n,"decl",zg(t,0,r),zg(t,r+1,-1),r)}var pm=n(9609),ym=n(7856),gm=n.n(ym),mm=function(t){var e=t.replace(/\\u[\dA-F]{4}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\u/g,""),16))}));return(e=(e=e.replace(/\\x([0-9a-f]{2})/gi,(function(t,e){return String.fromCharCode(parseInt(e,16))}))).replace(/\\[\d\d\d]{3}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\/g,""),8))}))).replace(/\\[\d\d\d]{2}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\/g,""),8))}))},vm=function(t){for(var e="",n=0;n>=0;){if(!((n=t.indexOf("=0)){e+=t,n=-1;break}e+=t.substr(0,n),(n=(t=t.substr(n+1)).indexOf("<\/script>"))>=0&&(n+=9,t=t.substr(n))}var r=mm(e);return(r=(r=(r=r.replace(/script>/gi,"#")).replace(/javascript:/gi,"#")).replace(/onerror=/gi,"onerror:")).replace(/')}if(void 0!==n)switch(y){case"flowchart":case"flowchart-v2":n(T,I_.bindFunctions);break;case"gantt":n(T,Fx.bindFunctions);break;case"class":case"classDiagram":n(T,Vv.bindFunctions);break;default:n(T)}else o.debug("CB = undefined!");mk.forEach((function(t){t()})),mk=[];var S="sandbox"===s.securityLevel?"#i"+t:"#d"+t,A=Zc(S).node();return null!==A&&"function"==typeof A.remove&&Zc(S).node().remove(),T},parse:function(t){var e=Av(),n=bv.detectInit(t,e);n&&o.debug("reinit ",n);var r,i=bv.detectType(t,e);switch(o.debug("Type "+i),i){case"git":(r=rw()).parser.yy=tw;break;case"flowchart":case"flowchart-v2":I_.clear(),(r=F_()).parser.yy=I_;break;case"sequence":(r=Gw()).parser.yy=gk;break;case"gantt":(r=zx()).parser.yy=Fx;break;case"class":case"classDiagram":(r=Jv()).parser.yy=Vv;break;case"state":case"stateDiagram":(r=Vk()).parser.yy=sT;break;case"info":o.debug("info info info"),(r=vw()).parser.yy=gw;break;case"pie":o.debug("pie"),(r=ww()).parser.yy=Cw;break;case"er":o.debug("er"),(r=r_()).parser.yy=e_;break;case"journey":o.debug("Journey"),(r=BT()).parser.yy=DT;break;case"requirement":case"requirementDiagram":o.debug("RequirementDiagram"),(r=Dw()).parser.yy=Fw}return r.parser.yy.graphType=i,r.parser.yy.parseError=function(t,e){throw{str:t,hash:e}},r.parse(t),r},parseDirective:function(t,e,n,r){try{if(void 0!==e)switch(e=e.trim(),n){case"open_directive":eE={};break;case"type_directive":eE.type=e.toLowerCase();break;case"arg_directive":eE.args=JSON.parse(e);break;case"close_directive":(function(t,e,n){switch(o.debug("Directive type=".concat(e.type," with args:"),e.args),e.type){case"init":case"initialize":["config"].forEach((function(t){void 0!==e.args[t]&&("flowchart-v2"===n&&(n="flowchart"),e.args[n]=e.args[t],delete e.args[t])})),o.debug("sanitize in handleDirective",e.args),mv(e.args),o.debug("sanitize in handleDirective (done)",e.args),e.args,Nv(e.args);break;case"wrap":case"nowrap":t&&t.setWrap&&t.setWrap("wrap"===e.type);break;case"themeCss":o.warn("themeCss encountered");break;default:o.warn("Unhandled directive: source: '%%{".concat(e.type,": ").concat(JSON.stringify(e.args?e.args:{}),"}%%"),e)}})(t,eE,r),eE=null}}catch(t){o.error("Error while rendering sequenceDiagram directive: ".concat(e," jison context: ").concat(n)),o.error(t.message)}},initialize:function(t){t&&t.fontFamily&&(t.themeVariables&&t.themeVariables.fontFamily||(t.themeVariables={fontFamily:t.fontFamily})),function(t){xv=uv({},t)}(t),t&&t.theme&&Fm[t.theme]?t.themeVariables=Fm[t.theme].getThemeVariables(t.themeVariables):t&&(t.themeVariables=Fm.default.getThemeVariables(t.themeVariables));var e="object"===JT(t)?function(t){return kv=uv({},wv),kv=uv(kv,t),t.theme&&(kv.themeVariables=Fm[t.theme].getThemeVariables(t.themeVariables)),Ev=Cv(kv,Tv),kv}(t):Sv();nE(e),s(e.logLevel)},reinitialize:function(){},getConfig:Av,setConfig:function(t){return uv(Ev,t),Av()},getSiteConfig:Sv,updateSiteConfig:function(t){return kv=uv(kv,t),Cv(kv,Tv),kv},reset:function(){Dv()},globalReset:function(){Dv(),nE(Av())},defaultConfig:wv});s(Av().logLevel),Dv(Av());const iE=rE;var aE=function(){oE.startOnLoad?iE.getConfig().startOnLoad&&oE.init():void 0===oE.startOnLoad&&(o.debug("In start, no config"),iE.getConfig().startOnLoad&&oE.init())};"undefined"!=typeof document&&window.addEventListener("load",(function(){aE()}),!1);var oE={startOnLoad:!0,htmlLabels:!0,mermaidAPI:iE,parse:iE.parse,render:iE.render,init:function(){var t,e,n=this,r=iE.getConfig();arguments.length>=2?(void 0!==arguments[0]&&(oE.sequenceConfig=arguments[0]),t=arguments[1]):t=arguments[0],"function"==typeof arguments[arguments.length-1]?(e=arguments[arguments.length-1],o.debug("Callback function found")):void 0!==r.mermaid&&("function"==typeof r.mermaid.callback?(e=r.mermaid.callback,o.debug("Callback function found")):o.debug("No Callback function found")),t=void 0===t?document.querySelectorAll(".mermaid"):"string"==typeof t?document.querySelectorAll(t):t instanceof window.Node?[t]:t,o.debug("Start On Load before: "+oE.startOnLoad),void 0!==oE.startOnLoad&&(o.debug("Start On Load inner: "+oE.startOnLoad),iE.updateSiteConfig({startOnLoad:oE.startOnLoad})),void 0!==oE.ganttConfig&&iE.updateSiteConfig({gantt:oE.ganttConfig});for(var i,a=new bv.initIdGeneratior(r.deterministicIds,r.deterministicIDSeed),s=function(r){var s=t[r];if(s.getAttribute("data-processed"))return"continue";s.setAttribute("data-processed",!0);var c="mermaid-".concat(a.next());i=s.innerHTML,i=bv.entityDecode(i).trim().replace(//gi,"
");var u=bv.detectInit(i);u&&o.debug("Detected early reinit: ",u);try{iE.render(c,i,(function(t,n){s.innerHTML=t,void 0!==e&&e(c),n&&n(s)}),s)}catch(t){o.warn("Syntax Error rendering"),o.warn(t),n.parseError&&n.parseError(t)}},c=0;c{t.exports={graphlib:n(6614),dagre:n(1463),intersect:n(8114),render:n(5787),util:n(8355),version:n(5689)}},9144:(t,e,n)=>{var r=n(8355);function i(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])}t.exports={default:i,normal:i,vee:function(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])},undirected:function(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])}}},5632:(t,e,n)=>{var r=n(8355),i=n(4322),a=n(1322);t.exports=function(t,e){var n,o=e.nodes().filter((function(t){return r.isSubgraph(e,t)})),s=t.selectAll("g.cluster").data(o,(function(t){return t}));return s.selectAll("*").remove(),s.enter().append("g").attr("class","cluster").attr("id",(function(t){return e.node(t).id})).style("opacity",0),s=t.selectAll("g.cluster"),r.applyTransition(s,e).style("opacity",1),s.each((function(t){var n=e.node(t),r=i.select(this);i.select(this).append("rect");var o=r.append("g").attr("class","label");a(o,n,n.clusterLabelPos)})),s.selectAll("rect").each((function(t){var n=e.node(t),a=i.select(this);r.applyStyle(a,n.style)})),n=s.exit?s.exit():s.selectAll(null),r.applyTransition(n,e).style("opacity",0).remove(),s}},6315:(t,e,n)=>{"use strict";var r=n(1034),i=n(1322),a=n(8355),o=n(4322);t.exports=function(t,e){var n,s=t.selectAll("g.edgeLabel").data(e.edges(),(function(t){return a.edgeToId(t)})).classed("update",!0);return s.exit().remove(),s.enter().append("g").classed("edgeLabel",!0).style("opacity",0),(s=t.selectAll("g.edgeLabel")).each((function(t){var n=o.select(this);n.select(".label").remove();var a=e.edge(t),s=i(n,e.edge(t),0,0).classed("label",!0),c=s.node().getBBox();a.labelId&&s.attr("id",a.labelId),r.has(a,"width")||(a.width=c.width),r.has(a,"height")||(a.height=c.height)})),n=s.exit?s.exit():s.selectAll(null),a.applyTransition(n,e).style("opacity",0).remove(),s}},940:(t,e,n)=>{"use strict";var r=n(1034),i=n(7584),a=n(8355),o=n(4322);function s(t,e){var n=(o.line||o.svg.line)().x((function(t){return t.x})).y((function(t){return t.y}));return(n.curve||n.interpolate)(t.curve),n(e)}t.exports=function(t,e,n){var c=t.selectAll("g.edgePath").data(e.edges(),(function(t){return a.edgeToId(t)})).classed("update",!0),u=function(t,e){var n=t.enter().append("g").attr("class","edgePath").style("opacity",0);return n.append("path").attr("class","path").attr("d",(function(t){var n=e.edge(t),i=e.node(t.v).elem;return s(n,r.range(n.points.length).map((function(){return e=(t=i).getBBox(),{x:(n=t.ownerSVGElement.getScreenCTM().inverse().multiply(t.getScreenCTM()).translate(e.width/2,e.height/2)).e,y:n.f};var t,e,n})))})),n.append("defs"),n}(c,e);!function(t,e){var n=t.exit();a.applyTransition(n,e).style("opacity",0).remove()}(c,e);var l=void 0!==c.merge?c.merge(u):c;return a.applyTransition(l,e).style("opacity",1),l.each((function(t){var n=o.select(this),r=e.edge(t);r.elem=this,r.id&&n.attr("id",r.id),a.applyClass(n,r.class,(n.classed("update")?"update ":"")+"edgePath")})),l.selectAll("path.path").each((function(t){var n=e.edge(t);n.arrowheadId=r.uniqueId("arrowhead");var c=o.select(this).attr("marker-end",(function(){return"url("+(t=location.href,e=n.arrowheadId,t.split("#")[0]+"#"+e+")");var t,e})).style("fill","none");a.applyTransition(c,e).attr("d",(function(t){return function(t,e){var n=t.edge(e),r=t.node(e.v),a=t.node(e.w),o=n.points.slice(1,n.points.length-1);return o.unshift(i(r,o[0])),o.push(i(a,o[o.length-1])),s(n,o)}(e,t)})),a.applyStyle(c,n.style)})),l.selectAll("defs *").remove(),l.selectAll("defs").each((function(t){var r=e.edge(t);(0,n[r.arrowhead])(o.select(this),r.arrowheadId,r,"arrowhead")})),l}},607:(t,e,n)=>{"use strict";var r=n(1034),i=n(1322),a=n(8355),o=n(4322);t.exports=function(t,e,n){var s,c=e.nodes().filter((function(t){return!a.isSubgraph(e,t)})),u=t.selectAll("g.node").data(c,(function(t){return t})).classed("update",!0);return u.exit().remove(),u.enter().append("g").attr("class","node").style("opacity",0),(u=t.selectAll("g.node")).each((function(t){var s=e.node(t),c=o.select(this);a.applyClass(c,s.class,(c.classed("update")?"update ":"")+"node"),c.select("g.label").remove();var u=c.append("g").attr("class","label"),l=i(u,s),h=n[s.shape],f=r.pick(l.node().getBBox(),"width","height");s.elem=this,s.id&&c.attr("id",s.id),s.labelId&&u.attr("id",s.labelId),r.has(s,"width")&&(f.width=s.width),r.has(s,"height")&&(f.height=s.height),f.width+=s.paddingLeft+s.paddingRight,f.height+=s.paddingTop+s.paddingBottom,u.attr("transform","translate("+(s.paddingLeft-s.paddingRight)/2+","+(s.paddingTop-s.paddingBottom)/2+")");var d=o.select(this);d.select(".label-container").remove();var p=h(d,f,s).classed("label-container",!0);a.applyStyle(p,s.style);var y=p.node().getBBox();s.width=y.width,s.height=y.height})),s=u.exit?u.exit():u.selectAll(null),a.applyTransition(s,e).style("opacity",0).remove(),u}},4322:(t,e,n)=>{var r;if(!r)try{r=n(7188)}catch(t){}r||(r=window.d3),t.exports=r},1463:(t,e,n)=>{var r;try{r=n(681)}catch(t){}r||(r=window.dagre),t.exports=r},6614:(t,e,n)=>{var r;try{r=n(8282)}catch(t){}r||(r=window.graphlib),t.exports=r},8114:(t,e,n)=>{t.exports={node:n(7584),circle:n(6587),ellipse:n(3260),polygon:n(5337),rect:n(8049)}},6587:(t,e,n)=>{var r=n(3260);t.exports=function(t,e,n){return r(t,e,e,n)}},3260:t=>{t.exports=function(t,e,n,r){var i=t.x,a=t.y,o=i-r.x,s=a-r.y,c=Math.sqrt(e*e*s*s+n*n*o*o),u=Math.abs(e*n*o/c);r.x{function e(t,e){return t*e>0}t.exports=function(t,n,r,i){var a,o,s,c,u,l,h,f,d,p,y,g,m;if(a=n.y-t.y,s=t.x-n.x,u=n.x*t.y-t.x*n.y,d=a*r.x+s*r.y+u,p=a*i.x+s*i.y+u,!(0!==d&&0!==p&&e(d,p)||(o=i.y-r.y,c=r.x-i.x,l=i.x*r.y-r.x*i.y,h=o*t.x+c*t.y+l,f=o*n.x+c*n.y+l,0!==h&&0!==f&&e(h,f)||0==(y=a*c-o*s))))return g=Math.abs(y/2),{x:(m=s*l-c*u)<0?(m-g)/y:(m+g)/y,y:(m=o*u-a*l)<0?(m-g)/y:(m+g)/y}}},7584:t=>{t.exports=function(t,e){return t.intersect(e)}},5337:(t,e,n)=>{var r=n(6808);t.exports=function(t,e,n){var i=t.x,a=t.y,o=[],s=Number.POSITIVE_INFINITY,c=Number.POSITIVE_INFINITY;e.forEach((function(t){s=Math.min(s,t.x),c=Math.min(c,t.y)}));for(var u=i-t.width/2-s,l=a-t.height/2-c,h=0;h1&&o.sort((function(t,e){var r=t.x-n.x,i=t.y-n.y,a=Math.sqrt(r*r+i*i),o=e.x-n.x,s=e.y-n.y,c=Math.sqrt(o*o+s*s);return a{t.exports=function(t,e){var n,r,i=t.x,a=t.y,o=e.x-i,s=e.y-a,c=t.width/2,u=t.height/2;return Math.abs(s)*c>Math.abs(o)*u?(s<0&&(u=-u),n=0===s?0:u*o/s,r=u):(o<0&&(c=-c),n=c,r=0===o?0:c*s/o),{x:i+n,y:a+r}}},8284:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){var n=t.append("foreignObject").attr("width","100000"),i=n.append("xhtml:div");i.attr("xmlns","http://www.w3.org/1999/xhtml");var a=e.label;switch(typeof a){case"function":i.insert(a);break;case"object":i.insert((function(){return a}));break;default:i.html(a)}r.applyStyle(i,e.labelStyle),i.style("display","inline-block"),i.style("white-space","nowrap");var o=i.node().getBoundingClientRect();return n.attr("width",o.width).attr("height",o.height),n}},1322:(t,e,n)=>{var r=n(7318),i=n(8284),a=n(8287);t.exports=function(t,e,n){var o=e.label,s=t.append("g");"svg"===e.labelType?a(s,e):"string"!=typeof o||"html"===e.labelType?i(s,e):r(s,e);var c,u=s.node().getBBox();switch(n){case"top":c=-e.height/2;break;case"bottom":c=e.height/2-u.height;break;default:c=-u.height/2}return s.attr("transform","translate("+-u.width/2+","+c+")"),s}},8287:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){var n=t;return n.node().appendChild(e.label),r.applyStyle(n,e.labelStyle),n}},7318:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){for(var n=t.append("text"),i=function(t){for(var e,n="",r=!1,i=0;i{var r;try{r={defaults:n(1747),each:n(6073),isFunction:n(3560),isPlainObject:n(8630),pick:n(9722),has:n(8721),range:n(6026),uniqueId:n(3955)}}catch(t){}r||(r=window._),t.exports=r},6381:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322);t.exports=function(t,e){var n=t.filter((function(){return!i.select(this).classed("update")}));function a(t){var n=e.node(t);return"translate("+n.x+","+n.y+")"}n.attr("transform",a),r.applyTransition(t,e).style("opacity",1).attr("transform",a),r.applyTransition(n.selectAll("rect"),e).attr("width",(function(t){return e.node(t).width})).attr("height",(function(t){return e.node(t).height})).attr("x",(function(t){return-e.node(t).width/2})).attr("y",(function(t){return-e.node(t).height/2}))}},4577:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322),a=n(1034);t.exports=function(t,e){function n(t){var n=e.edge(t);return a.has(n,"x")?"translate("+n.x+","+n.y+")":""}t.filter((function(){return!i.select(this).classed("update")})).attr("transform",n),r.applyTransition(t,e).style("opacity",1).attr("transform",n)}},4849:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322);t.exports=function(t,e){function n(t){var n=e.node(t);return"translate("+n.x+","+n.y+")"}t.filter((function(){return!i.select(this).classed("update")})).attr("transform",n),r.applyTransition(t,e).style("opacity",1).attr("transform",n)}},5787:(t,e,n)=>{var r=n(1034),i=n(4322),a=n(1463).layout;t.exports=function(){var t=n(607),e=n(5632),i=n(6315),u=n(940),l=n(4849),h=n(4577),f=n(6381),d=n(4418),p=n(9144),y=function(n,y){!function(t){t.nodes().forEach((function(e){var n=t.node(e);r.has(n,"label")||t.children(e).length||(n.label=e),r.has(n,"paddingX")&&r.defaults(n,{paddingLeft:n.paddingX,paddingRight:n.paddingX}),r.has(n,"paddingY")&&r.defaults(n,{paddingTop:n.paddingY,paddingBottom:n.paddingY}),r.has(n,"padding")&&r.defaults(n,{paddingLeft:n.padding,paddingRight:n.padding,paddingTop:n.padding,paddingBottom:n.padding}),r.defaults(n,o),r.each(["paddingLeft","paddingRight","paddingTop","paddingBottom"],(function(t){n[t]=Number(n[t])})),r.has(n,"width")&&(n._prevWidth=n.width),r.has(n,"height")&&(n._prevHeight=n.height)})),t.edges().forEach((function(e){var n=t.edge(e);r.has(n,"label")||(n.label=""),r.defaults(n,s)}))}(y);var g=c(n,"output"),m=c(g,"clusters"),v=c(g,"edgePaths"),b=i(c(g,"edgeLabels"),y),_=t(c(g,"nodes"),y,d);a(y),l(_,y),h(b,y),u(v,y,p);var x=e(m,y);f(x,y),function(t){r.each(t.nodes(),(function(e){var n=t.node(e);r.has(n,"_prevWidth")?n.width=n._prevWidth:delete n.width,r.has(n,"_prevHeight")?n.height=n._prevHeight:delete n.height,delete n._prevWidth,delete n._prevHeight}))}(y)};return y.createNodes=function(e){return arguments.length?(t=e,y):t},y.createClusters=function(t){return arguments.length?(e=t,y):e},y.createEdgeLabels=function(t){return arguments.length?(i=t,y):i},y.createEdgePaths=function(t){return arguments.length?(u=t,y):u},y.shapes=function(t){return arguments.length?(d=t,y):d},y.arrows=function(t){return arguments.length?(p=t,y):p},y};var o={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"},s={arrowhead:"normal",curve:i.curveLinear};function c(t,e){var n=t.select("g."+e);return n.empty()&&(n=t.append("g").attr("class",e)),n}},4418:(t,e,n)=>{"use strict";var r=n(8049),i=n(3260),a=n(6587),o=n(5337);t.exports={rect:function(t,e,n){var i=t.insert("rect",":first-child").attr("rx",n.rx).attr("ry",n.ry).attr("x",-e.width/2).attr("y",-e.height/2).attr("width",e.width).attr("height",e.height);return n.intersect=function(t){return r(n,t)},i},ellipse:function(t,e,n){var r=e.width/2,a=e.height/2,o=t.insert("ellipse",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("rx",r).attr("ry",a);return n.intersect=function(t){return i(n,r,a,t)},o},circle:function(t,e,n){var r=Math.max(e.width,e.height)/2,i=t.insert("circle",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("r",r);return n.intersect=function(t){return a(n,r,t)},i},diamond:function(t,e,n){var r=e.width*Math.SQRT2/2,i=e.height*Math.SQRT2/2,a=[{x:0,y:-i},{x:-r,y:0},{x:0,y:i},{x:r,y:0}],s=t.insert("polygon",":first-child").attr("points",a.map((function(t){return t.x+","+t.y})).join(" "));return n.intersect=function(t){return o(n,a,t)},s}}},8355:(t,e,n)=>{var r=n(1034);t.exports={isSubgraph:function(t,e){return!!t.children(e).length},edgeToId:function(t){return a(t.v)+":"+a(t.w)+":"+a(t.name)},applyStyle:function(t,e){e&&t.attr("style",e)},applyClass:function(t,e,n){e&&t.attr("class",e).attr("class",n+" "+t.attr("class"))},applyTransition:function(t,e){var n=e.graph();if(r.isPlainObject(n)){var i=n.transition;if(r.isFunction(i))return i(t)}return t}};var i=/:/g;function a(t){return t?String(t).replace(i,"\\:"):""}},5689:t=>{t.exports="0.6.4"},7188:(t,e,n)=>{"use strict";n.r(e),n.d(e,{FormatSpecifier:()=>rc,active:()=>Kr,arc:()=>rx,area:()=>ux,areaRadial:()=>vx,ascending:()=>i,autoType:()=>Do,axisBottom:()=>it,axisLeft:()=>at,axisRight:()=>rt,axisTop:()=>nt,bisect:()=>u,bisectLeft:()=>c,bisectRight:()=>s,bisector:()=>a,blob:()=>hs,brush:()=>Si,brushSelection:()=>Ti,brushX:()=>Ei,brushY:()=>Ci,buffer:()=>ds,chord:()=>Ri,clientPoint:()=>Nn,cluster:()=>_d,color:()=>We,contourDensity:()=>to,contours:()=>Ga,create:()=>N_,creator:()=>ie,cross:()=>f,csv:()=>vs,csvFormat:()=>vo,csvFormatBody:()=>bo,csvFormatRow:()=>xo,csvFormatRows:()=>_o,csvFormatValue:()=>wo,csvParse:()=>go,csvParseRows:()=>mo,cubehelix:()=>Pa,curveBasis:()=>Kx,curveBasisClosed:()=>tw,curveBasisOpen:()=>nw,curveBundle:()=>iw,curveCardinal:()=>sw,curveCardinalClosed:()=>uw,curveCardinalOpen:()=>hw,curveCatmullRom:()=>pw,curveCatmullRomClosed:()=>gw,curveCatmullRomOpen:()=>vw,curveLinear:()=>ax,curveLinearClosed:()=>_w,curveMonotoneX:()=>Aw,curveMonotoneY:()=>Mw,curveNatural:()=>Ow,curveStep:()=>Lw,curveStepAfter:()=>Rw,curveStepBefore:()=>Iw,customEvent:()=>ge,descending:()=>d,deviation:()=>g,dispatch:()=>ft,drag:()=>so,dragDisable:()=>Se,dragEnable:()=>Ae,dsv:()=>ms,dsvFormat:()=>po,easeBack:()=>as,easeBackIn:()=>rs,easeBackInOut:()=>as,easeBackOut:()=>is,easeBounce:()=>ts,easeBounceIn:()=>Jo,easeBounceInOut:()=>es,easeBounceOut:()=>ts,easeCircle:()=>Qo,easeCircleIn:()=>Xo,easeCircleInOut:()=>Qo,easeCircleOut:()=>Zo,easeCubic:()=>Gr,easeCubicIn:()=>Wr,easeCubicInOut:()=>Gr,easeCubicOut:()=>Vr,easeElastic:()=>cs,easeElasticIn:()=>ss,easeElasticInOut:()=>us,easeElasticOut:()=>cs,easeExp:()=>Go,easeExpIn:()=>Wo,easeExpInOut:()=>Go,easeExpOut:()=>Vo,easeLinear:()=>Bo,easePoly:()=>jo,easePolyIn:()=>Fo,easePolyInOut:()=>jo,easePolyOut:()=>Po,easeQuad:()=>Ro,easeQuadIn:()=>Lo,easeQuadInOut:()=>Ro,easeQuadOut:()=>Io,easeSin:()=>Ho,easeSinIn:()=>Uo,easeSinInOut:()=>Ho,easeSinOut:()=>qo,entries:()=>da,event:()=>le,extent:()=>m,forceCenter:()=>Ss,forceCollide:()=>Ys,forceLink:()=>qs,forceManyBody:()=>Gs,forceRadial:()=>Xs,forceSimulation:()=>Vs,forceX:()=>Zs,forceY:()=>Qs,format:()=>cc,formatDefaultLocale:()=>dc,formatLocale:()=>fc,formatPrefix:()=>uc,formatSpecifier:()=>nc,geoAlbers:()=>If,geoAlbersUsa:()=>Rf,geoArea:()=>uu,geoAzimuthalEqualArea:()=>Yf,geoAzimuthalEqualAreaRaw:()=>jf,geoAzimuthalEquidistant:()=>Uf,geoAzimuthalEquidistantRaw:()=>zf,geoBounds:()=>el,geoCentroid:()=>dl,geoCircle:()=>Tl,geoClipAntimeridian:()=>Rl,geoClipCircle:()=>Fl,geoClipExtent:()=>zl,geoClipRectangle:()=>Yl,geoConicConformal:()=>Gf,geoConicConformalRaw:()=>Vf,geoConicEqualArea:()=>Lf,geoConicEqualAreaRaw:()=>Bf,geoConicEquidistant:()=>Kf,geoConicEquidistantRaw:()=>Qf,geoContains:()=>ch,geoDistance:()=>Jl,geoEqualEarth:()=>ad,geoEqualEarthRaw:()=>id,geoEquirectangular:()=>Zf,geoEquirectangularRaw:()=>Xf,geoGnomonic:()=>sd,geoGnomonicRaw:()=>od,geoGraticule:()=>hh,geoGraticule10:()=>fh,geoIdentity:()=>cd,geoInterpolate:()=>dh,geoLength:()=>Zl,geoMercator:()=>Hf,geoMercatorRaw:()=>qf,geoNaturalEarth1:()=>ld,geoNaturalEarth1Raw:()=>ud,geoOrthographic:()=>fd,geoOrthographicRaw:()=>hd,geoPath:()=>gf,geoProjection:()=>Nf,geoProjectionMutator:()=>Df,geoRotation:()=>xl,geoStereographic:()=>pd,geoStereographicRaw:()=>dd,geoStream:()=>Zc,geoTransform:()=>mf,geoTransverseMercator:()=>gd,geoTransverseMercatorRaw:()=>yd,gray:()=>va,hcl:()=>Sa,hierarchy:()=>wd,histogram:()=>D,hsl:()=>rn,html:()=>Es,image:()=>_s,interpolate:()=>An,interpolateArray:()=>_n,interpolateBasis:()=>cn,interpolateBasisClosed:()=>un,interpolateBlues:()=>r_,interpolateBrBG:()=>yb,interpolateBuGn:()=>Bb,interpolateBuPu:()=>Ib,interpolateCividis:()=>p_,interpolateCool:()=>m_,interpolateCubehelix:()=>Lp,interpolateCubehelixDefault:()=>y_,interpolateCubehelixLong:()=>Ip,interpolateDate:()=>wn,interpolateDiscrete:()=>_p,interpolateGnBu:()=>Fb,interpolateGreens:()=>a_,interpolateGreys:()=>s_,interpolateHcl:()=>Dp,interpolateHclLong:()=>Op,interpolateHsl:()=>Sp,interpolateHslLong:()=>Ap,interpolateHue:()=>xp,interpolateInferno:()=>A_,interpolateLab:()=>Mp,interpolateMagma:()=>S_,interpolateNumber:()=>kn,interpolateNumberArray:()=>vn,interpolateObject:()=>Tn,interpolateOrRd:()=>jb,interpolateOranges:()=>d_,interpolatePRGn:()=>mb,interpolatePiYG:()=>bb,interpolatePlasma:()=>M_,interpolatePuBu:()=>qb,interpolatePuBuGn:()=>zb,interpolatePuOr:()=>xb,interpolatePuRd:()=>$b,interpolatePurples:()=>u_,interpolateRainbow:()=>b_,interpolateRdBu:()=>kb,interpolateRdGy:()=>Eb,interpolateRdPu:()=>Vb,interpolateRdYlBu:()=>Sb,interpolateRdYlGn:()=>Mb,interpolateReds:()=>h_,interpolateRgb:()=>pn,interpolateRgbBasis:()=>gn,interpolateRgbBasisClosed:()=>mn,interpolateRound:()=>wp,interpolateSinebow:()=>k_,interpolateSpectral:()=>Db,interpolateString:()=>Sn,interpolateTransformCss:()=>dr,interpolateTransformSvg:()=>pr,interpolateTurbo:()=>T_,interpolateViridis:()=>C_,interpolateWarm:()=>g_,interpolateYlGn:()=>Qb,interpolateYlGnBu:()=>Xb,interpolateYlOrBr:()=>Jb,interpolateYlOrRd:()=>e_,interpolateZoom:()=>Ep,interrupt:()=>ir,interval:()=>ek,isoFormat:()=>Jw,isoParse:()=>tk,json:()=>ws,keys:()=>ha,lab:()=>ba,lch:()=>Ca,line:()=>cx,lineRadial:()=>mx,linkHorizontal:()=>Sx,linkRadial:()=>Mx,linkVertical:()=>Ax,local:()=>O_,map:()=>ea,matcher:()=>mt,max:()=>I,mean:()=>R,median:()=>F,merge:()=>P,min:()=>j,mouse:()=>On,namespace:()=>Et,namespaces:()=>Tt,nest:()=>na,now:()=>qn,pack:()=>Vd,packEnclose:()=>Ad,packSiblings:()=>zd,pairs:()=>l,partition:()=>Jd,path:()=>$i,permute:()=>Y,pie:()=>fx,piecewise:()=>Rp,pointRadial:()=>bx,polygonArea:()=>Pp,polygonCentroid:()=>jp,polygonContains:()=>Hp,polygonHull:()=>qp,polygonLength:()=>$p,precisionFixed:()=>pc,precisionPrefix:()=>yc,precisionRound:()=>gc,quadtree:()=>Ls,quantile:()=>O,quantize:()=>Fp,radialArea:()=>vx,radialLine:()=>mx,randomBates:()=>Qp,randomExponential:()=>Kp,randomIrwinHall:()=>Zp,randomLogNormal:()=>Xp,randomNormal:()=>Gp,randomUniform:()=>Vp,range:()=>k,rgb:()=>Ze,ribbon:()=>Qi,scaleBand:()=>oy,scaleDiverging:()=>Qv,scaleDivergingLog:()=>Kv,scaleDivergingPow:()=>tb,scaleDivergingSqrt:()=>eb,scaleDivergingSymlog:()=>Jv,scaleIdentity:()=>wy,scaleImplicit:()=>iy,scaleLinear:()=>xy,scaleLog:()=>Dy,scaleOrdinal:()=>ay,scalePoint:()=>cy,scalePow:()=>Yy,scaleQuantile:()=>Uy,scaleQuantize:()=>qy,scaleSequential:()=>Hv,scaleSequentialLog:()=>$v,scaleSequentialPow:()=>Vv,scaleSequentialQuantile:()=>Xv,scaleSequentialSqrt:()=>Gv,scaleSequentialSymlog:()=>Wv,scaleSqrt:()=>zy,scaleSymlog:()=>Iy,scaleThreshold:()=>Hy,scaleTime:()=>Dv,scaleUtc:()=>zv,scan:()=>z,schemeAccent:()=>ib,schemeBlues:()=>n_,schemeBrBG:()=>pb,schemeBuGn:()=>Ob,schemeBuPu:()=>Lb,schemeCategory10:()=>rb,schemeDark2:()=>ab,schemeGnBu:()=>Rb,schemeGreens:()=>i_,schemeGreys:()=>o_,schemeOrRd:()=>Pb,schemeOranges:()=>f_,schemePRGn:()=>gb,schemePaired:()=>ob,schemePastel1:()=>sb,schemePastel2:()=>cb,schemePiYG:()=>vb,schemePuBu:()=>Ub,schemePuBuGn:()=>Yb,schemePuOr:()=>_b,schemePuRd:()=>Hb,schemePurples:()=>c_,schemeRdBu:()=>wb,schemeRdGy:()=>Tb,schemeRdPu:()=>Wb,schemeRdYlBu:()=>Cb,schemeRdYlGn:()=>Ab,schemeReds:()=>l_,schemeSet1:()=>ub,schemeSet2:()=>lb,schemeSet3:()=>hb,schemeSpectral:()=>Nb,schemeTableau10:()=>fb,schemeYlGn:()=>Zb,schemeYlGnBu:()=>Gb,schemeYlOrBr:()=>Kb,schemeYlOrRd:()=>t_,select:()=>Te,selectAll:()=>L_,selection:()=>ke,selector:()=>pt,selectorAll:()=>gt,set:()=>la,shuffle:()=>U,stack:()=>Yw,stackOffsetDiverging:()=>Uw,stackOffsetExpand:()=>zw,stackOffsetNone:()=>Fw,stackOffsetSilhouette:()=>qw,stackOffsetWiggle:()=>Hw,stackOrderAppearance:()=>$w,stackOrderAscending:()=>Vw,stackOrderDescending:()=>Xw,stackOrderInsideOut:()=>Zw,stackOrderNone:()=>Pw,stackOrderReverse:()=>Qw,stratify:()=>ip,style:()=>Rt,sum:()=>q,svg:()=>Cs,symbol:()=>Gx,symbolCircle:()=>Nx,symbolCross:()=>Dx,symbolDiamond:()=>Lx,symbolSquare:()=>jx,symbolStar:()=>Px,symbolTriangle:()=>zx,symbolWye:()=>Wx,symbols:()=>Vx,text:()=>ys,thresholdFreedmanDiaconis:()=>B,thresholdScott:()=>L,thresholdSturges:()=>N,tickFormat:()=>by,tickIncrement:()=>A,tickStep:()=>M,ticks:()=>S,timeDay:()=>bg,timeDays:()=>_g,timeFormat:()=>am,timeFormatDefaultLocale:()=>Cv,timeFormatLocale:()=>rm,timeFriday:()=>ug,timeFridays:()=>gg,timeHour:()=>wg,timeHours:()=>kg,timeInterval:()=>Vy,timeMillisecond:()=>Dg,timeMilliseconds:()=>Og,timeMinute:()=>Eg,timeMinutes:()=>Cg,timeMonday:()=>ag,timeMondays:()=>fg,timeMonth:()=>Ky,timeMonths:()=>Jy,timeParse:()=>om,timeSaturday:()=>lg,timeSaturdays:()=>mg,timeSecond:()=>Ag,timeSeconds:()=>Mg,timeSunday:()=>ig,timeSundays:()=>hg,timeThursday:()=>cg,timeThursdays:()=>yg,timeTuesday:()=>og,timeTuesdays:()=>dg,timeWednesday:()=>sg,timeWednesdays:()=>pg,timeWeek:()=>ig,timeWeeks:()=>hg,timeYear:()=>Xy,timeYears:()=>Zy,timeout:()=>Qn,timer:()=>Wn,timerFlush:()=>Vn,touch:()=>Dn,touches:()=>I_,transition:()=>qr,transpose:()=>H,tree:()=>hp,treemap:()=>gp,treemapBinary:()=>mp,treemapDice:()=>Kd,treemapResquarify:()=>bp,treemapSlice:()=>fp,treemapSliceDice:()=>vp,treemapSquarify:()=>yp,tsv:()=>bs,tsvFormat:()=>Co,tsvFormatBody:()=>So,tsvFormatRow:()=>Mo,tsvFormatRows:()=>Ao,tsvFormatValue:()=>No,tsvParse:()=>To,tsvParseRows:()=>Eo,utcDay:()=>Xg,utcDays:()=>Zg,utcFormat:()=>sm,utcFriday:()=>jg,utcFridays:()=>Wg,utcHour:()=>Rv,utcHours:()=>Fv,utcMillisecond:()=>Dg,utcMilliseconds:()=>Og,utcMinute:()=>jv,utcMinutes:()=>Yv,utcMonday:()=>Ig,utcMondays:()=>Ug,utcMonth:()=>Bv,utcMonths:()=>Lv,utcParse:()=>cm,utcSaturday:()=>Yg,utcSaturdays:()=>Vg,utcSecond:()=>Ag,utcSeconds:()=>Mg,utcSunday:()=>Lg,utcSundays:()=>zg,utcThursday:()=>Pg,utcThursdays:()=>$g,utcTuesday:()=>Rg,utcTuesdays:()=>qg,utcWednesday:()=>Fg,utcWednesdays:()=>Hg,utcWeek:()=>Lg,utcWeeks:()=>zg,utcYear:()=>Kg,utcYears:()=>Jg,values:()=>fa,variance:()=>y,version:()=>r,voronoi:()=>zk,window:()=>Ot,xml:()=>Ts,zip:()=>W,zoom:()=>eT,zoomIdentity:()=>$k,zoomTransform:()=>Wk});var r="5.16.0";function i(t,e){return te?1:t>=e?0:NaN}function a(t){var e;return 1===t.length&&(e=t,t=function(t,n){return i(e(t),n)}),{left:function(e,n,r,i){for(null==r&&(r=0),null==i&&(i=e.length);r>>1;t(e[a],n)<0?r=a+1:i=a}return r},right:function(e,n,r,i){for(null==r&&(r=0),null==i&&(i=e.length);r>>1;t(e[a],n)>0?i=a:r=a+1}return r}}}var o=a(i),s=o.right,c=o.left;const u=s;function l(t,e){null==e&&(e=h);for(var n=0,r=t.length-1,i=t[0],a=new Array(r<0?0:r);nt?1:e>=t?0:NaN}function p(t){return null===t?NaN:+t}function y(t,e){var n,r,i=t.length,a=0,o=-1,s=0,c=0;if(null==e)for(;++o1)return c/(a-1)}function g(t,e){var n=y(t,e);return n?Math.sqrt(n):n}function m(t,e){var n,r,i,a=t.length,o=-1;if(null==e){for(;++o=n)for(r=i=n;++on&&(r=n),i=n)for(r=i=n;++on&&(r=n),i0)return[t];if((r=e0)for(t=Math.ceil(t/o),e=Math.floor(e/o),a=new Array(i=Math.ceil(e-t+1));++s=0?(a>=T?10:a>=E?5:a>=C?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=T?10:a>=E?5:a>=C?2:1)}function M(t,e,n){var r=Math.abs(e-t)/Math.max(0,n),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),a=r/i;return a>=T?i*=10:a>=E?i*=5:a>=C&&(i*=2),eh;)f.pop(),--d;var p,y=new Array(d+1);for(i=0;i<=d;++i)(p=y[i]=[]).x0=i>0?f[i-1]:l,p.x1=i=1)return+n(t[r-1],r-1,t);var r,i=(r-1)*e,a=Math.floor(i),o=+n(t[a],a,t);return o+(+n(t[a+1],a+1,t)-o)*(i-a)}}function B(t,e,n){return t=_.call(t,p).sort(i),Math.ceil((n-e)/(2*(O(t,.75)-O(t,.25))*Math.pow(t.length,-1/3)))}function L(t,e,n){return Math.ceil((n-e)/(3.5*g(t)*Math.pow(t.length,-1/3)))}function I(t,e){var n,r,i=t.length,a=-1;if(null==e){for(;++a=n)for(r=n;++ar&&(r=n)}else for(;++a=n)for(r=n;++ar&&(r=n);return r}function R(t,e){var n,r=t.length,i=r,a=-1,o=0;if(null==e)for(;++a=0;)for(e=(r=t[i]).length;--e>=0;)n[--o]=r[e];return n}function j(t,e){var n,r,i=t.length,a=-1;if(null==e){for(;++a=n)for(r=n;++an&&(r=n)}else for(;++a=n)for(r=n;++an&&(r=n);return r}function Y(t,e){for(var n=e.length,r=new Array(n);n--;)r[n]=t[e[n]];return r}function z(t,e){if(n=t.length){var n,r,a=0,o=0,s=t[o];for(null==e&&(e=i);++a=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function lt(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;ae?1:t>=e?0:NaN}bt.prototype={constructor:bt,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var kt="http://www.w3.org/1999/xhtml";const Tt={svg:"http://www.w3.org/2000/svg",xhtml:kt,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Et(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),Tt.hasOwnProperty(e)?{space:Tt[e],local:t}:t}function Ct(t){return function(){this.removeAttribute(t)}}function St(t){return function(){this.removeAttributeNS(t.space,t.local)}}function At(t,e){return function(){this.setAttribute(t,e)}}function Mt(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function Nt(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function Dt(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function Ot(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function Bt(t){return function(){this.style.removeProperty(t)}}function Lt(t,e,n){return function(){this.style.setProperty(t,e,n)}}function It(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Rt(t,e){return t.style.getPropertyValue(e)||Ot(t).getComputedStyle(t,null).getPropertyValue(e)}function Ft(t){return function(){delete this[t]}}function Pt(t,e){return function(){this[t]=e}}function jt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function Yt(t){return t.trim().split(/^|\s+/)}function zt(t){return t.classList||new Ut(t)}function Ut(t){this._node=t,this._names=Yt(t.getAttribute("class")||"")}function qt(t,e){for(var n=zt(t),r=-1,i=e.length;++r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var ue={},le=null;function he(t,e,n){return t=fe(t,e,n),function(e){var n=e.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||t.call(this,e)}}function fe(t,e,n){return function(r){var i=le;le=r;try{t.call(this,this.__data__,e,n)}finally{le=i}}}function de(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function pe(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=x&&(x=_+1);!(b=m[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=wt);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?Bt:"function"==typeof e?It:Lt)(t,e,null==n?"":n)):Rt(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?Ft:"function"==typeof e?jt:Pt)(t,e)):this.node()[t]},classed:function(t,e){var n=Yt(t+"");if(arguments.length<2){for(var r=zt(this.node()),i=-1,a=n.length;++i>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Ge(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Ge(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Fe.exec(t))?new Qe(e[1],e[2],e[3],1):(e=Pe.exec(t))?new Qe(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=je.exec(t))?Ge(e[1],e[2],e[3],e[4]):(e=Ye.exec(t))?Ge(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=ze.exec(t))?en(e[1],e[2]/100,e[3]/100,1):(e=Ue.exec(t))?en(e[1],e[2]/100,e[3]/100,e[4]):qe.hasOwnProperty(t)?Ve(qe[t]):"transparent"===t?new Qe(NaN,NaN,NaN,0):null}function Ve(t){return new Qe(t>>16&255,t>>8&255,255&t,1)}function Ge(t,e,n,r){return r<=0&&(t=e=n=NaN),new Qe(t,e,n,r)}function Xe(t){return t instanceof De||(t=We(t)),t?new Qe((t=t.rgb()).r,t.g,t.b,t.opacity):new Qe}function Ze(t,e,n,r){return 1===arguments.length?Xe(t):new Qe(t,e,n,null==r?1:r)}function Qe(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Ke(){return"#"+tn(this.r)+tn(this.g)+tn(this.b)}function Je(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function tn(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function en(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new an(t,e,n,r)}function nn(t){if(t instanceof an)return new an(t.h,t.s,t.l,t.opacity);if(t instanceof De||(t=We(t)),!t)return new an;if(t instanceof an)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new an(o,s,c,t.opacity)}function rn(t,e,n,r){return 1===arguments.length?nn(t):new an(t,e,n,null==r?1:r)}function an(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function on(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function sn(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}function cn(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r180||n<-180?n-360*Math.round(n/360):n):ln(isNaN(t)?e:t)}function dn(t,e){var n=e-t;return n?hn(t,n):ln(isNaN(t)?e:t)}Me(De,We,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:He,formatHex:He,formatHsl:function(){return nn(this).formatHsl()},formatRgb:$e,toString:$e}),Me(Qe,Ze,Ne(De,{brighter:function(t){return t=null==t?Oe:Math.pow(Oe,t),new Qe(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Qe(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Ke,formatHex:Ke,formatRgb:Je,toString:Je})),Me(an,rn,Ne(De,{brighter:function(t){return t=null==t?Oe:Math.pow(Oe,t),new an(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new an(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new Qe(on(t>=240?t-240:t+120,i,r),on(t,i,r),on(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const pn=function t(e){var n=function(t){return 1==(t=+t)?dn:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):ln(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=Ze(t)).r,(e=Ze(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=dn(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function yn(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;na&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:kn(n,r)})),a=Cn.lastIndex;return a=0&&e._call.call(null,t),e=e._next;--In}function Gn(){jn=(Pn=zn.now())+Yn,In=Rn=0;try{Vn()}finally{In=0,function(){for(var t,e,n=Bn,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Bn=e);Ln=t,Zn(r)}(),jn=0}}function Xn(){var t=zn.now(),e=t-Pn;e>1e3&&(Yn-=e,Pn=t)}function Zn(t){In||(Rn&&(Rn=clearTimeout(Rn)),t-jn>24?(t<1/0&&(Rn=setTimeout(Gn,t-zn.now()-Yn)),Fn&&(Fn=clearInterval(Fn))):(Fn||(Pn=zn.now(),Fn=setInterval(Xn,1e3)),In=1,Un(Gn)))}function Qn(t,e,n){var r=new $n;return e=null==e?0:+e,r.restart((function(n){r.stop(),t(n+e)}),e,n),r}$n.prototype=Wn.prototype={constructor:$n,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?qn():+n)+(null==e?0:+e),this._next||Ln===this||(Ln?Ln._next=this:Bn=this,Ln=this),this._call=t,this._time=n,Zn()},stop:function(){this._call&&(this._call=null,this._time=1/0,Zn())}};var Kn=ft("start","end","cancel","interrupt"),Jn=[];function tr(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return Qn(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function nr(t,e){var n=rr(t,e);if(n.state>3)throw new Error("too late; already running");return n}function rr(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function ir(t,e){var n,r,i,a=t.__transition,o=!0;if(a){for(i in e=null==e?null:e+"",a)(n=a[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}var ar,or,sr,cr,ur=180/Math.PI,lr={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function hr(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:kn(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:kn(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:kn(t,n)},{i:s-2,x:kn(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?er:nr;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var Ir=ke.prototype.constructor;function Rr(t){return function(){this.style.removeProperty(t)}}function Fr(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Pr(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Fr(t,a,n)),r}return a._value=e,a}function jr(t){return function(e){this.textContent=t.call(this,e)}}function Yr(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&jr(r)),e}return r._value=t,r}var zr=0;function Ur(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function qr(t){return ke().transition(t)}function Hr(){return++zr}var $r=ke.prototype;function Wr(t){return t*t*t}function Vr(t){return--t*t*t+1}function Gr(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}Ur.prototype=qr.prototype={constructor:Ur,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=pt(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o1&&n.name===e)return new Ur([[t]],Qr,e,+r);return null}function Jr(t){return function(){return t}}function ti(t,e,n){this.target=t,this.type=e,this.selection=n}function ei(){le.stopImmediatePropagation()}function ni(){le.preventDefault(),le.stopImmediatePropagation()}var ri={name:"drag"},ii={name:"space"},ai={name:"handle"},oi={name:"center"};function si(t){return[+t[0],+t[1]]}function ci(t){return[si(t[0]),si(t[1])]}function ui(t){return function(e){return Dn(e,le.touches,t)}}var li={name:"x",handles:["w","e"].map(vi),input:function(t,e){return null==t?null:[[+t[0],e[0][1]],[+t[1],e[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},hi={name:"y",handles:["n","s"].map(vi),input:function(t,e){return null==t?null:[[e[0][0],+t[0]],[e[1][0],+t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},fi={name:"xy",handles:["n","w","e","s","nw","ne","sw","se"].map(vi),input:function(t){return null==t?null:ci(t)},output:function(t){return t}},di={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},pi={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},yi={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},gi={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},mi={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1};function vi(t){return{type:t}}function bi(){return!le.ctrlKey&&!le.button}function _i(){var t=this.ownerSVGElement||this;return t.hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function xi(){return navigator.maxTouchPoints||"ontouchstart"in this}function wi(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function ki(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function Ti(t){var e=t.__brush;return e?e.dim.output(e.selection):null}function Ei(){return Ai(li)}function Ci(){return Ai(hi)}function Si(){return Ai(fi)}function Ai(t){var e,n=_i,r=bi,i=xi,a=!0,o=ft("start","brush","end"),s=6;function c(e){var n=e.property("__brush",y).selectAll(".overlay").data([vi("overlay")]);n.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",di.overlay).merge(n).each((function(){var t=wi(this).extent;Te(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])})),e.selectAll(".selection").data([vi("selection")]).enter().append("rect").attr("class","selection").attr("cursor",di.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var r=e.selectAll(".handle").data(t.handles,(function(t){return t.type}));r.exit().remove(),r.enter().append("rect").attr("class",(function(t){return"handle handle--"+t.type})).attr("cursor",(function(t){return di[t.type]})),e.each(u).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",f).filter(i).on("touchstart.brush",f).on("touchmove.brush",d).on("touchend.brush touchcancel.brush",p).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function u(){var t=Te(this),e=wi(this).selection;e?(t.selectAll(".selection").style("display",null).attr("x",e[0][0]).attr("y",e[0][1]).attr("width",e[1][0]-e[0][0]).attr("height",e[1][1]-e[0][1]),t.selectAll(".handle").style("display",null).attr("x",(function(t){return"e"===t.type[t.type.length-1]?e[1][0]-s/2:e[0][0]-s/2})).attr("y",(function(t){return"s"===t.type[0]?e[1][1]-s/2:e[0][1]-s/2})).attr("width",(function(t){return"n"===t.type||"s"===t.type?e[1][0]-e[0][0]+s:s})).attr("height",(function(t){return"e"===t.type||"w"===t.type?e[1][1]-e[0][1]+s:s}))):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function l(t,e,n){var r=t.__brush.emitter;return!r||n&&r.clean?new h(t,e,n):r}function h(t,e,n){this.that=t,this.args=e,this.state=t.__brush,this.active=0,this.clean=n}function f(){if((!e||le.touches)&&r.apply(this,arguments)){var n,i,o,s,c,h,f,d,p,y,g,m=this,v=le.target.__data__.type,b="selection"===(a&&le.metaKey?v="overlay":v)?ri:a&&le.altKey?oi:ai,_=t===hi?null:gi[v],x=t===li?null:mi[v],w=wi(m),k=w.extent,T=w.selection,E=k[0][0],C=k[0][1],S=k[1][0],A=k[1][1],M=0,N=0,D=_&&x&&a&&le.shiftKey,O=le.touches?ui(le.changedTouches[0].identifier):On,B=O(m),L=B,I=l(m,arguments,!0).beforestart();"overlay"===v?(T&&(p=!0),w.selection=T=[[n=t===hi?E:B[0],o=t===li?C:B[1]],[c=t===hi?S:n,f=t===li?A:o]]):(n=T[0][0],o=T[0][1],c=T[1][0],f=T[1][1]),i=n,s=o,h=c,d=f;var R=Te(m).attr("pointer-events","none"),F=R.selectAll(".overlay").attr("cursor",di[v]);if(le.touches)I.moved=j,I.ended=z;else{var P=Te(le.view).on("mousemove.brush",j,!0).on("mouseup.brush",z,!0);a&&P.on("keydown.brush",U,!0).on("keyup.brush",q,!0),Se(le.view)}ei(),ir(m),u.call(m),I.start()}function j(){var t=O(m);!D||y||g||(Math.abs(t[0]-L[0])>Math.abs(t[1]-L[1])?g=!0:y=!0),L=t,p=!0,ni(),Y()}function Y(){var t;switch(M=L[0]-B[0],N=L[1]-B[1],b){case ii:case ri:_&&(M=Math.max(E-n,Math.min(S-c,M)),i=n+M,h=c+M),x&&(N=Math.max(C-o,Math.min(A-f,N)),s=o+N,d=f+N);break;case ai:_<0?(M=Math.max(E-n,Math.min(S-n,M)),i=n+M,h=c):_>0&&(M=Math.max(E-c,Math.min(S-c,M)),i=n,h=c+M),x<0?(N=Math.max(C-o,Math.min(A-o,N)),s=o+N,d=f):x>0&&(N=Math.max(C-f,Math.min(A-f,N)),s=o,d=f+N);break;case oi:_&&(i=Math.max(E,Math.min(S,n-M*_)),h=Math.max(E,Math.min(S,c+M*_))),x&&(s=Math.max(C,Math.min(A,o-N*x)),d=Math.max(C,Math.min(A,f+N*x)))}h0&&(n=i-M),x<0?f=d-N:x>0&&(o=s-N),b=ii,F.attr("cursor",di.selection),Y());break;default:return}ni()}function q(){switch(le.keyCode){case 16:D&&(y=g=D=!1,Y());break;case 18:b===oi&&(_<0?c=h:_>0&&(n=i),x<0?f=d:x>0&&(o=s),b=ai,Y());break;case 32:b===ii&&(le.altKey?(_&&(c=h-M*_,n=i+M*_),x&&(f=d-N*x,o=s+N*x),b=oi):(_<0?c=h:_>0&&(n=i),x<0?f=d:x>0&&(o=s),b=ai),F.attr("cursor",di[v]),Y());break;default:return}ni()}}function d(){l(this,arguments).moved()}function p(){l(this,arguments).ended()}function y(){var e=this.__brush||{selection:null};return e.extent=ci(n.apply(this,arguments)),e.dim=t,e}return c.move=function(e,n){e.selection?e.on("start.brush",(function(){l(this,arguments).beforestart().start()})).on("interrupt.brush end.brush",(function(){l(this,arguments).end()})).tween("brush",(function(){var e=this,r=e.__brush,i=l(e,arguments),a=r.selection,o=t.input("function"==typeof n?n.apply(this,arguments):n,r.extent),s=An(a,o);function c(t){r.selection=1===t&&null===o?null:s(t),u.call(e),i.brush()}return null!==a&&null!==o?c:c(1)})):e.each((function(){var e=this,r=arguments,i=e.__brush,a=t.input("function"==typeof n?n.apply(e,r):n,i.extent),o=l(e,r).beforestart();ir(e),i.selection=null===a?null:a,u.call(e),o.start().brush().end()}))},c.clear=function(t){c.move(t,null)},h.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting?(this.starting=!1,this.emit("start")):this.emit("brush"),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(e){ge(new ti(c,e,t.output(this.state.selection)),o.apply,o,[e,this.that,this.args])}},c.extent=function(t){return arguments.length?(n="function"==typeof t?t:Jr(ci(t)),c):n},c.filter=function(t){return arguments.length?(r="function"==typeof t?t:Jr(!!t),c):r},c.touchable=function(t){return arguments.length?(i="function"==typeof t?t:Jr(!!t),c):i},c.handleSize=function(t){return arguments.length?(s=+t,c):s},c.keyModifiers=function(t){return arguments.length?(a=!!t,c):a},c.on=function(){var t=o.on.apply(o,arguments);return t===o?c:t},c}var Mi=Math.cos,Ni=Math.sin,Di=Math.PI,Oi=Di/2,Bi=2*Di,Li=Math.max;function Ii(t){return function(e,n){return t(e.source.value+e.target.value,n.source.value+n.target.value)}}function Ri(){var t=0,e=null,n=null,r=null;function i(i){var a,o,s,c,u,l,h=i.length,f=[],d=k(h),p=[],y=[],g=y.groups=new Array(h),m=new Array(h*h);for(a=0,u=-1;++uzi)if(Math.abs(l*s-c*u)>zi&&i){var f=n-a,d=r-o,p=s*s+c*c,y=f*f+d*d,g=Math.sqrt(p),m=Math.sqrt(h),v=i*Math.tan((ji-Math.acos((p+h-y)/(2*g*m)))/2),b=v/m,_=v/g;Math.abs(b-1)>zi&&(this._+="L"+(t+b*u)+","+(e+b*l)),this._+="A"+i+","+i+",0,0,"+ +(l*f>u*d)+","+(this._x1=t+_*s)+","+(this._y1=e+_*c)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,r,i,a){t=+t,e=+e,a=!!a;var o=(n=+n)*Math.cos(r),s=n*Math.sin(r),c=t+o,u=e+s,l=1^a,h=a?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+c+","+u:(Math.abs(this._x1-c)>zi||Math.abs(this._y1-u)>zi)&&(this._+="L"+c+","+u),n&&(h<0&&(h=h%Yi+Yi),h>Ui?this._+="A"+n+","+n+",0,1,"+l+","+(t-o)+","+(e-s)+"A"+n+","+n+",0,1,"+l+","+(this._x1=c)+","+(this._y1=u):h>zi&&(this._+="A"+n+","+n+",0,"+ +(h>=ji)+","+l+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};const $i=Hi;function Wi(t){return t.source}function Vi(t){return t.target}function Gi(t){return t.radius}function Xi(t){return t.startAngle}function Zi(t){return t.endAngle}function Qi(){var t=Wi,e=Vi,n=Gi,r=Xi,i=Zi,a=null;function o(){var o,s=Fi.call(arguments),c=t.apply(this,s),u=e.apply(this,s),l=+n.apply(this,(s[0]=c,s)),h=r.apply(this,s)-Oi,f=i.apply(this,s)-Oi,d=l*Mi(h),p=l*Ni(h),y=+n.apply(this,(s[0]=u,s)),g=r.apply(this,s)-Oi,m=i.apply(this,s)-Oi;if(a||(a=o=$i()),a.moveTo(d,p),a.arc(0,0,l,h,f),h===g&&f===m||(a.quadraticCurveTo(0,0,y*Mi(g),y*Ni(g)),a.arc(0,0,y,g,m)),a.quadraticCurveTo(0,0,d,p),a.closePath(),o)return a=null,o+""||null}return o.radius=function(t){return arguments.length?(n="function"==typeof t?t:Pi(+t),o):n},o.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:Pi(+t),o):r},o.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:Pi(+t),o):i},o.source=function(e){return arguments.length?(t=e,o):t},o.target=function(t){return arguments.length?(e=t,o):e},o.context=function(t){return arguments.length?(a=null==t?null:t,o):a},o}var Ki="$";function Ji(){}function ta(t,e){var n=new Ji;if(t instanceof Ji)t.each((function(t,e){n.set(e,t)}));else if(Array.isArray(t)){var r,i=-1,a=t.length;if(null==e)for(;++i=r.length)return null!=t&&n.sort(t),null!=e?e(n):n;for(var c,u,l,h=-1,f=n.length,d=r[i++],p=ea(),y=o();++hr.length)return n;var o,s=i[a-1];return null!=e&&a>=r.length?o=n.entries():(o=[],n.each((function(e,n){o.push({key:n,values:t(e,a)})}))),null!=s?o.sort((function(t,e){return s(t.key,e.key)})):o}(a(t,0,aa,oa),0)},key:function(t){return r.push(t),n},sortKeys:function(t){return i[r.length-1]=t,n},sortValues:function(e){return t=e,n},rollup:function(t){return e=t,n}}}function ra(){return{}}function ia(t,e,n){t[e]=n}function aa(){return ea()}function oa(t,e,n){t.set(e,n)}function sa(){}var ca=ea.prototype;function ua(t,e){var n=new sa;if(t instanceof sa)t.each((function(t){n.add(t)}));else if(t){var r=-1,i=t.length;if(null==e)for(;++r.008856451679035631?Math.pow(t,1/3):t/ga+4/29}function wa(t){return t>6/29?t*t*t:ga*(t-4/29)}function ka(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Ta(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Ea(t){if(t instanceof Aa)return new Aa(t.h,t.c,t.l,t.opacity);if(t instanceof _a||(t=ma(t)),0===t.a&&0===t.b)return new Aa(NaN,0r!=d>r&&n<(f-u)*(r-l)/(d-l)+u&&(i=-i)}return i}function $a(t,e,n){var r,i,a,o;return function(t,e,n){return(e[0]-t[0])*(n[1]-t[1])==(n[0]-t[0])*(e[1]-t[1])}(t,e,n)&&(i=t[r=+(t[0]===e[0])],a=n[r],o=e[r],i<=a&&a<=o||o<=a&&a<=i)}function Wa(){}var Va=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function Ga(){var t=1,e=1,n=N,r=s;function i(t){var e=n(t);if(Array.isArray(e))e=e.slice().sort(za);else{var r=m(t),i=r[0],o=r[1];e=M(i,o,e),e=k(Math.floor(i/e)*e,Math.floor(o/e)*e,e)}return e.map((function(e){return a(t,e)}))}function a(n,i){var a=[],s=[];return function(n,r,i){var a,s,c,u,l,h,f=new Array,d=new Array;for(a=s=-1,u=n[0]>=r,Va[u<<1].forEach(p);++a=r,Va[c|u<<1].forEach(p);for(Va[u<<0].forEach(p);++s=r,l=n[s*t]>=r,Va[u<<1|l<<2].forEach(p);++a=r,h=l,l=n[s*t+a+1]>=r,Va[c|u<<1|l<<2|h<<3].forEach(p);Va[u|l<<3].forEach(p)}for(a=-1,l=n[s*t]>=r,Va[l<<2].forEach(p);++a=r,Va[l<<2|h<<3].forEach(p);function p(t){var e,n,r=[t[0][0]+a,t[0][1]+s],c=[t[1][0]+a,t[1][1]+s],u=o(r),l=o(c);(e=d[u])?(n=f[l])?(delete d[e.end],delete f[n.start],e===n?(e.ring.push(c),i(e.ring)):f[e.start]=d[n.end]={start:e.start,end:n.end,ring:e.ring.concat(n.ring)}):(delete d[e.end],e.ring.push(c),d[e.end=l]=e):(e=f[l])?(n=d[u])?(delete f[e.start],delete d[n.end],e===n?(e.ring.push(c),i(e.ring)):f[n.start]=d[e.end]={start:n.start,end:e.end,ring:n.ring.concat(e.ring)}):(delete f[e.start],e.ring.unshift(r),f[e.start=u]=e):f[u]=d[l]={start:u,end:l,ring:[r,c]}}Va[l<<3].forEach(p)}(n,i,(function(t){r(t,n,i),function(t){for(var e=0,n=t.length,r=t[n-1][1]*t[0][0]-t[n-1][0]*t[0][1];++e0?a.push([t]):s.push(t)})),s.forEach((function(t){for(var e,n=0,r=a.length;n0&&o0&&s0&&a>0))throw new Error("invalid size");return t=r,e=a,i},i.thresholds=function(t){return arguments.length?(n="function"==typeof t?t:Array.isArray(t)?Ua(Ya.call(t)):Ua(t),i):n},i.smooth=function(t){return arguments.length?(r=t?s:Wa,i):r===s},i}function Xa(t,e,n){for(var r=t.width,i=t.height,a=1+(n<<1),o=0;o=n&&(s>=a&&(c-=t.data[s-a+o*r]),e.data[s-n+o*r]=c/Math.min(s+1,r-1+a-s,a))}function Za(t,e,n){for(var r=t.width,i=t.height,a=1+(n<<1),o=0;o=n&&(s>=a&&(c-=t.data[o+(s-a)*r]),e.data[o+(s-n)*r]=c/Math.min(s+1,i-1+a-s,a))}function Qa(t){return t[0]}function Ka(t){return t[1]}function Ja(){return 1}function to(){var t=Qa,e=Ka,n=Ja,r=960,i=500,a=20,o=2,s=3*a,c=r+2*s>>o,u=i+2*s>>o,l=Ua(20);function h(r){var i=new Float32Array(c*u),h=new Float32Array(c*u);r.forEach((function(r,a,l){var h=+t(r,a,l)+s>>o,f=+e(r,a,l)+s>>o,d=+n(r,a,l);h>=0&&h=0&&f>o),Za({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o),Xa({width:c,height:u,data:i},{width:c,height:u,data:h},a>>o),Za({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o),Xa({width:c,height:u,data:i},{width:c,height:u,data:h},a>>o),Za({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o);var d=l(i);if(!Array.isArray(d)){var p=I(i);d=M(0,p,d),(d=k(0,Math.floor(p/d)*d,d)).shift()}return Ga().thresholds(d).size([c,u])(i).map(f)}function f(t){return t.value*=Math.pow(2,-2*o),t.coordinates.forEach(d),t}function d(t){t.forEach(p)}function p(t){t.forEach(y)}function y(t){t[0]=t[0]*Math.pow(2,o)-s,t[1]=t[1]*Math.pow(2,o)-s}function g(){return c=r+2*(s=3*a)>>o,u=i+2*s>>o,h}return h.x=function(e){return arguments.length?(t="function"==typeof e?e:Ua(+e),h):t},h.y=function(t){return arguments.length?(e="function"==typeof t?t:Ua(+t),h):e},h.weight=function(t){return arguments.length?(n="function"==typeof t?t:Ua(+t),h):n},h.size=function(t){if(!arguments.length)return[r,i];var e=Math.ceil(t[0]),n=Math.ceil(t[1]);if(!(e>=0||e>=0))throw new Error("invalid size");return r=e,i=n,g()},h.cellSize=function(t){if(!arguments.length)return 1<=1))throw new Error("invalid cell size");return o=Math.floor(Math.log(t)/Math.LN2),g()},h.thresholds=function(t){return arguments.length?(l="function"==typeof t?t:Array.isArray(t)?Ua(Ya.call(t)):Ua(t),h):l},h.bandwidth=function(t){if(!arguments.length)return Math.sqrt(a*(a+1));if(!((t=+t)>=0))throw new Error("invalid bandwidth");return a=Math.round((Math.sqrt(4*t*t+1)-1)/2),g()},h}function eo(t){return function(){return t}}function no(t,e,n,r,i,a,o,s,c,u){this.target=t,this.type=e,this.subject=n,this.identifier=r,this.active=i,this.x=a,this.y=o,this.dx=s,this.dy=c,this._=u}function ro(){return!le.ctrlKey&&!le.button}function io(){return this.parentNode}function ao(t){return null==t?{x:le.x,y:le.y}:t}function oo(){return navigator.maxTouchPoints||"ontouchstart"in this}function so(){var t,e,n,r,i=ro,a=io,o=ao,s=oo,c={},u=ft("start","drag","end"),l=0,h=0;function f(t){t.on("mousedown.drag",d).filter(s).on("touchstart.drag",g).on("touchmove.drag",m).on("touchend.drag touchcancel.drag",v).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(){if(!r&&i.apply(this,arguments)){var o=b("mouse",a.apply(this,arguments),On,this,arguments);o&&(Te(le.view).on("mousemove.drag",p,!0).on("mouseup.drag",y,!0),Se(le.view),Ee(),n=!1,t=le.clientX,e=le.clientY,o("start"))}}function p(){if(Ce(),!n){var r=le.clientX-t,i=le.clientY-e;n=r*r+i*i>h}c.mouse("drag")}function y(){Te(le.view).on("mousemove.drag mouseup.drag",null),Ae(le.view,n),Ce(),c.mouse("end")}function g(){if(i.apply(this,arguments)){var t,e,n=le.changedTouches,r=a.apply(this,arguments),o=n.length;for(t=0;t=a?c=!0:10===(r=t.charCodeAt(o++))?u=!0:13===r&&(u=!0,10===t.charCodeAt(o)&&++o),t.slice(i+1,e-1).replace(/""/g,'"')}for(;o9999?"+"+fo(t,6):fo(t,4)}(t.getUTCFullYear())+"-"+fo(t.getUTCMonth()+1,2)+"-"+fo(t.getUTCDate(),2)+(i?"T"+fo(e,2)+":"+fo(n,2)+":"+fo(r,2)+"."+fo(i,3)+"Z":r?"T"+fo(e,2)+":"+fo(n,2)+":"+fo(r,2)+"Z":n||e?"T"+fo(e,2)+":"+fo(n,2)+"Z":"")}(t):e.test(t+="")?'"'+t.replace(/"/g,'""')+'"':t}return{parse:function(t,e){var n,i,a=r(t,(function(t,r){if(n)return n(t,r-1);i=t,n=e?function(t,e){var n=lo(t);return function(r,i){return e(n(r),i,t)}}(t,e):lo(t)}));return a.columns=i||[],a},parseRows:r,format:function(e,n){return null==n&&(n=ho(e)),[n.map(o).join(t)].concat(i(e,n)).join("\n")},formatBody:function(t,e){return null==e&&(e=ho(t)),i(t,e).join("\n")},formatRows:function(t){return t.map(a).join("\n")},formatRow:a,formatValue:o}}var yo=po(","),go=yo.parse,mo=yo.parseRows,vo=yo.format,bo=yo.formatBody,_o=yo.formatRows,xo=yo.formatRow,wo=yo.formatValue,ko=po("\t"),To=ko.parse,Eo=ko.parseRows,Co=ko.format,So=ko.formatBody,Ao=ko.formatRows,Mo=ko.formatRow,No=ko.formatValue;function Do(t){for(var e in t){var n,r,i=t[e].trim();if(i)if("true"===i)i=!0;else if("false"===i)i=!1;else if("NaN"===i)i=NaN;else if(isNaN(n=+i)){if(!(r=i.match(/^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/)))continue;Oo&&r[4]&&!r[7]&&(i=i.replace(/-/g,"/").replace(/T/," ")),i=new Date(i)}else i=n;else i=null;t[e]=i}return t}var Oo=new Date("2019-01-01T00:00").getHours()||new Date("2019-07-01T00:00").getHours();function Bo(t){return+t}function Lo(t){return t*t}function Io(t){return t*(2-t)}function Ro(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}var Fo=function t(e){function n(t){return Math.pow(t,e)}return e=+e,n.exponent=t,n}(3),Po=function t(e){function n(t){return 1-Math.pow(1-t,e)}return e=+e,n.exponent=t,n}(3),jo=function t(e){function n(t){return((t*=2)<=1?Math.pow(t,e):2-Math.pow(2-t,e))/2}return e=+e,n.exponent=t,n}(3),Yo=Math.PI,zo=Yo/2;function Uo(t){return 1==+t?1:1-Math.cos(t*zo)}function qo(t){return Math.sin(t*zo)}function Ho(t){return(1-Math.cos(Yo*t))/2}function $o(t){return 1.0009775171065494*(Math.pow(2,-10*t)-.0009765625)}function Wo(t){return $o(1-+t)}function Vo(t){return 1-$o(t)}function Go(t){return((t*=2)<=1?$o(1-t):2-$o(t-1))/2}function Xo(t){return 1-Math.sqrt(1-t*t)}function Zo(t){return Math.sqrt(1- --t*t)}function Qo(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}var Ko=7.5625;function Jo(t){return 1-ts(1-t)}function ts(t){return(t=+t)<.36363636363636365?Ko*t*t:t<.7272727272727273?Ko*(t-=.5454545454545454)*t+.75:t<.9090909090909091?Ko*(t-=.8181818181818182)*t+.9375:Ko*(t-=.9545454545454546)*t+.984375}function es(t){return((t*=2)<=1?1-ts(1-t):ts(t-1)+1)/2}var ns=1.70158,rs=function t(e){function n(t){return(t=+t)*t*(e*(t-1)+t)}return e=+e,n.overshoot=t,n}(ns),is=function t(e){function n(t){return--t*t*((t+1)*e+t)+1}return e=+e,n.overshoot=t,n}(ns),as=function t(e){function n(t){return((t*=2)<1?t*t*((e+1)*t-e):(t-=2)*t*((e+1)*t+e)+2)/2}return e=+e,n.overshoot=t,n}(ns),os=2*Math.PI,ss=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=os);function i(t){return e*$o(- --t)*Math.sin((r-t)/n)}return i.amplitude=function(e){return t(e,n*os)},i.period=function(n){return t(e,n)},i}(1,.3),cs=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=os);function i(t){return 1-e*$o(t=+t)*Math.sin((t+r)/n)}return i.amplitude=function(e){return t(e,n*os)},i.period=function(n){return t(e,n)},i}(1,.3),us=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=os);function i(t){return((t=2*t-1)<0?e*$o(-t)*Math.sin((r-t)/n):2-e*$o(t)*Math.sin((r+t)/n))/2}return i.amplitude=function(e){return t(e,n*os)},i.period=function(n){return t(e,n)},i}(1,.3);function ls(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.blob()}function hs(t,e){return fetch(t,e).then(ls)}function fs(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.arrayBuffer()}function ds(t,e){return fetch(t,e).then(fs)}function ps(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.text()}function ys(t,e){return fetch(t,e).then(ps)}function gs(t){return function(e,n,r){return 2===arguments.length&&"function"==typeof n&&(r=n,n=void 0),ys(e,n).then((function(e){return t(e,r)}))}}function ms(t,e,n,r){3===arguments.length&&"function"==typeof n&&(r=n,n=void 0);var i=po(t);return ys(e,n).then((function(t){return i.parse(t,r)}))}var vs=gs(go),bs=gs(To);function _s(t,e){return new Promise((function(n,r){var i=new Image;for(var a in e)i[a]=e[a];i.onerror=r,i.onload=function(){n(i)},i.src=t}))}function xs(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);if(204!==t.status&&205!==t.status)return t.json()}function ws(t,e){return fetch(t,e).then(xs)}function ks(t){return function(e,n){return ys(e,n).then((function(e){return(new DOMParser).parseFromString(e,t)}))}}const Ts=ks("application/xml");var Es=ks("text/html"),Cs=ks("image/svg+xml");function Ss(t,e){var n;function r(){var r,i,a=n.length,o=0,s=0;for(r=0;r=(a=(y+m)/2))?y=a:m=a,(l=n>=(o=(g+v)/2))?g=o:v=o,i=d,!(d=d[h=l<<1|u]))return i[h]=p,t;if(s=+t._x.call(null,d.data),c=+t._y.call(null,d.data),e===s&&n===c)return p.next=d,i?i[h]=p:t._root=p,t;do{i=i?i[h]=new Array(4):t._root=new Array(4),(u=e>=(a=(y+m)/2))?y=a:m=a,(l=n>=(o=(g+v)/2))?g=o:v=o}while((h=l<<1|u)==(f=(c>=o)<<1|s>=a));return i[f]=d,i[h]=p,t}function Ds(t,e,n,r,i){this.node=t,this.x0=e,this.y0=n,this.x1=r,this.y1=i}function Os(t){return t[0]}function Bs(t){return t[1]}function Ls(t,e,n){var r=new Is(null==e?Os:e,null==n?Bs:n,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Is(t,e,n,r,i,a){this._x=t,this._y=e,this._x0=n,this._y0=r,this._x1=i,this._y1=a,this._root=void 0}function Rs(t){for(var e={data:t.data},n=e;t=t.next;)n=n.next={data:t.data};return e}var Fs=Ls.prototype=Is.prototype;function Ps(t){return t.x+t.vx}function js(t){return t.y+t.vy}function Ys(t){var e,n,r=1,i=1;function a(){for(var t,a,s,c,u,l,h,f=e.length,d=0;dc+d||iu+d||as.index){var p=c-o.x-o.vx,y=u-o.y-o.vy,g=p*p+y*y;gt.r&&(t.r=t[e].r)}function s(){if(e){var r,i,a=e.length;for(n=new Array(a),r=0;rl&&(l=r),ih&&(h=i));if(c>l||u>h)return this;for(this.cover(c,u).cover(l,h),n=0;nt||t>=i||r>e||e>=a;)switch(s=(ef||(a=c.y0)>d||(o=c.x1)=m)<<1|t>=g)&&(c=p[p.length-1],p[p.length-1]=p[p.length-1-u],p[p.length-1-u]=c)}else{var v=t-+this._x.call(null,y.data),b=e-+this._y.call(null,y.data),_=v*v+b*b;if(_=(s=(p+g)/2))?p=s:g=s,(l=o>=(c=(y+m)/2))?y=c:m=c,e=d,!(d=d[h=l<<1|u]))return this;if(!d.length)break;(e[h+1&3]||e[h+2&3]||e[h+3&3])&&(n=e,f=h)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):e?(i?e[h]=i:delete e[h],(d=e[0]||e[1]||e[2]||e[3])&&d===(e[3]||e[2]||e[1]||e[0])&&!d.length&&(n?n[f]=d:this._root=d),this):(this._root=i,this)},Fs.removeAll=function(t){for(var e=0,n=t.length;e1?(null==n?s.remove(t):s.set(t,d(n)),e):s.get(t)},find:function(e,n,r){var i,a,o,s,c,u=0,l=t.length;for(null==r?r=1/0:r*=r,u=0;u1?(u.on(t,n),e):u.on(t)}}}function Gs(){var t,e,n,r,i=As(-30),a=1,o=1/0,s=.81;function c(r){var i,a=t.length,o=Ls(t,Hs,$s).visitAfter(l);for(n=r,i=0;i=o)){(t.data!==e||t.next)&&(0===l&&(d+=(l=Ms())*l),0===h&&(d+=(h=Ms())*h),d1?r[0]+r.slice(2):r,+t.slice(n+1)]}function Js(t){return(t=Ks(Math.abs(t)))?t[1]:NaN}var tc,ec=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function nc(t){if(!(e=ec.exec(t)))throw new Error("invalid format: "+t);var e;return new rc({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function rc(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function ic(t,e){var n=Ks(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}nc.prototype=rc.prototype,rc.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const ac={"%":function(t,e){return(100*t).toFixed(e)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},g:function(t,e){return t.toPrecision(e)},o:function(t){return Math.round(t).toString(8)},p:function(t,e){return ic(100*t,e)},r:ic,s:function(t,e){var n=Ks(t,e);if(!n)return t+"";var r=n[0],i=n[1],a=i-(tc=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,o=r.length;return a===o?r:a>o?r+new Array(a-o+1).join("0"):a>0?r.slice(0,a)+"."+r.slice(a):"0."+new Array(1-a).join("0")+Ks(t,Math.max(0,e+a-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}};function oc(t){return t}var sc,cc,uc,lc=Array.prototype.map,hc=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function fc(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?oc:(e=lc.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,a=[],o=0,s=e[0],c=0;i>0&&s>0&&(c+s+1>r&&(s=Math.max(1,r-c)),a.push(t.substring(i-=s,i+s)),!((c+=s+1)>r));)s=e[o=(o+1)%e.length];return a.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",a=void 0===t.currency?"":t.currency[1]+"",o=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?oc:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(lc.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",u=void 0===t.minus?"-":t.minus+"",l=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=nc(t)).fill,n=t.align,h=t.sign,f=t.symbol,d=t.zero,p=t.width,y=t.comma,g=t.precision,m=t.trim,v=t.type;"n"===v?(y=!0,v="g"):ac[v]||(void 0===g&&(g=12),m=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var b="$"===f?i:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?a:/[%p]/.test(v)?c:"",x=ac[v],w=/[defgprs%]/.test(v);function k(t){var i,a,c,f=b,k=_;if("c"===v)k=x(t)+k,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?l:x(Math.abs(t),g),m&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),T&&0==+t&&"+"!==h&&(T=!1),f=(T?"("===h?h:u:"-"===h||"("===h?"":h)+f,k=("s"===v?hc[8+tc/3]:"")+k+(T&&"("===h?")":""),w)for(i=-1,a=t.length;++i(c=t.charCodeAt(i))||c>57){k=(46===c?o+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}y&&!d&&(t=r(t,1/0));var E=f.length+t.length+k.length,C=E>1)+f+t+k+C.slice(E);break;default:t=C+f+t+k}return s(t)}return g=void 0===g?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,g)):Math.max(0,Math.min(20,g)),k.toString=function(){return t+""},k}return{format:h,formatPrefix:function(t,e){var n=h(((t=nc(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Js(e)/3))),i=Math.pow(10,-r),a=hc[8+r/3];return function(t){return n(i*t)+a}}}}function dc(t){return sc=fc(t),cc=sc.format,uc=sc.formatPrefix,sc}function pc(t){return Math.max(0,-Js(Math.abs(t)))}function yc(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Js(e)/3)))-Js(Math.abs(t)))}function gc(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Js(e)-Js(t))+1}function mc(){return new vc}function vc(){this.reset()}dc({decimal:".",thousands:",",grouping:[3],currency:["$",""],minus:"-"}),vc.prototype={constructor:vc,reset:function(){this.s=this.t=0},add:function(t){_c(bc,t,this.t),_c(this,bc.s,this.s),this.s?this.t+=bc.t:this.s=bc.t},valueOf:function(){return this.s}};var bc=new vc;function _c(t,e,n){var r=t.s=e+n,i=r-e,a=r-i;t.t=e-a+(n-i)}var xc=1e-6,wc=1e-12,kc=Math.PI,Tc=kc/2,Ec=kc/4,Cc=2*kc,Sc=180/kc,Ac=kc/180,Mc=Math.abs,Nc=Math.atan,Dc=Math.atan2,Oc=Math.cos,Bc=Math.ceil,Lc=Math.exp,Ic=(Math.floor,Math.log),Rc=Math.pow,Fc=Math.sin,Pc=Math.sign||function(t){return t>0?1:t<0?-1:0},jc=Math.sqrt,Yc=Math.tan;function zc(t){return t>1?0:t<-1?kc:Math.acos(t)}function Uc(t){return t>1?Tc:t<-1?-Tc:Math.asin(t)}function qc(t){return(t=Fc(t/2))*t}function Hc(){}function $c(t,e){t&&Vc.hasOwnProperty(t.type)&&Vc[t.type](t,e)}var Wc={Feature:function(t,e){$c(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r=0?1:-1,i=r*n,a=Oc(e=(e*=Ac)/2+Ec),o=Fc(e),s=eu*o,c=tu*a+s*Oc(i),u=s*r*Fc(i);nu.add(Dc(u,c)),Jc=t,tu=a,eu=o}function uu(t){return ru.reset(),Zc(t,iu),2*ru}function lu(t){return[Dc(t[1],t[0]),Uc(t[2])]}function hu(t){var e=t[0],n=t[1],r=Oc(n);return[r*Oc(e),r*Fc(e),Fc(n)]}function fu(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function du(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function pu(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function yu(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function gu(t){var e=jc(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}var mu,vu,bu,_u,xu,wu,ku,Tu,Eu,Cu,Su,Au,Mu,Nu,Du,Ou,Bu,Lu,Iu,Ru,Fu,Pu,ju,Yu,zu,Uu,qu=mc(),Hu={point:$u,lineStart:Vu,lineEnd:Gu,polygonStart:function(){Hu.point=Xu,Hu.lineStart=Zu,Hu.lineEnd=Qu,qu.reset(),iu.polygonStart()},polygonEnd:function(){iu.polygonEnd(),Hu.point=$u,Hu.lineStart=Vu,Hu.lineEnd=Gu,nu<0?(mu=-(bu=180),vu=-(_u=90)):qu>xc?_u=90:qu<-1e-6&&(vu=-90),Cu[0]=mu,Cu[1]=bu},sphere:function(){mu=-(bu=180),vu=-(_u=90)}};function $u(t,e){Eu.push(Cu=[mu=t,bu=t]),e_u&&(_u=e)}function Wu(t,e){var n=hu([t*Ac,e*Ac]);if(Tu){var r=du(Tu,n),i=du([r[1],-r[0],0],r);gu(i),i=lu(i);var a,o=t-xu,s=o>0?1:-1,c=i[0]*Sc*s,u=Mc(o)>180;u^(s*xu_u&&(_u=a):u^(s*xu<(c=(c+360)%360-180)&&c_u&&(_u=e)),u?tKu(mu,bu)&&(bu=t):Ku(t,bu)>Ku(mu,bu)&&(mu=t):bu>=mu?(tbu&&(bu=t)):t>xu?Ku(mu,t)>Ku(mu,bu)&&(bu=t):Ku(t,bu)>Ku(mu,bu)&&(mu=t)}else Eu.push(Cu=[mu=t,bu=t]);e_u&&(_u=e),Tu=n,xu=t}function Vu(){Hu.point=Wu}function Gu(){Cu[0]=mu,Cu[1]=bu,Hu.point=$u,Tu=null}function Xu(t,e){if(Tu){var n=t-xu;qu.add(Mc(n)>180?n+(n>0?360:-360):n)}else wu=t,ku=e;iu.point(t,e),Wu(t,e)}function Zu(){iu.lineStart()}function Qu(){Xu(wu,ku),iu.lineEnd(),Mc(qu)>xc&&(mu=-(bu=180)),Cu[0]=mu,Cu[1]=bu,Tu=null}function Ku(t,e){return(e-=t)<0?e+360:e}function Ju(t,e){return t[0]-e[0]}function tl(t,e){return t[0]<=t[1]?t[0]<=e&&e<=t[1]:eKu(r[0],r[1])&&(r[1]=i[1]),Ku(i[0],r[1])>Ku(r[0],r[1])&&(r[0]=i[0])):a.push(r=i);for(o=-1/0,e=0,r=a[n=a.length-1];e<=n;r=i,++e)i=a[e],(s=Ku(r[1],i[0]))>o&&(o=s,mu=i[0],bu=r[1])}return Eu=Cu=null,mu===1/0||vu===1/0?[[NaN,NaN],[NaN,NaN]]:[[mu,vu],[bu,_u]]}var nl={sphere:Hc,point:rl,lineStart:al,lineEnd:cl,polygonStart:function(){nl.lineStart=ul,nl.lineEnd=ll},polygonEnd:function(){nl.lineStart=al,nl.lineEnd=cl}};function rl(t,e){t*=Ac;var n=Oc(e*=Ac);il(n*Oc(t),n*Fc(t),Fc(e))}function il(t,e,n){++Su,Mu+=(t-Mu)/Su,Nu+=(e-Nu)/Su,Du+=(n-Du)/Su}function al(){nl.point=ol}function ol(t,e){t*=Ac;var n=Oc(e*=Ac);Yu=n*Oc(t),zu=n*Fc(t),Uu=Fc(e),nl.point=sl,il(Yu,zu,Uu)}function sl(t,e){t*=Ac;var n=Oc(e*=Ac),r=n*Oc(t),i=n*Fc(t),a=Fc(e),o=Dc(jc((o=zu*a-Uu*i)*o+(o=Uu*r-Yu*a)*o+(o=Yu*i-zu*r)*o),Yu*r+zu*i+Uu*a);Au+=o,Ou+=o*(Yu+(Yu=r)),Bu+=o*(zu+(zu=i)),Lu+=o*(Uu+(Uu=a)),il(Yu,zu,Uu)}function cl(){nl.point=rl}function ul(){nl.point=hl}function ll(){fl(Pu,ju),nl.point=rl}function hl(t,e){Pu=t,ju=e,t*=Ac,e*=Ac,nl.point=fl;var n=Oc(e);Yu=n*Oc(t),zu=n*Fc(t),Uu=Fc(e),il(Yu,zu,Uu)}function fl(t,e){t*=Ac;var n=Oc(e*=Ac),r=n*Oc(t),i=n*Fc(t),a=Fc(e),o=zu*a-Uu*i,s=Uu*r-Yu*a,c=Yu*i-zu*r,u=jc(o*o+s*s+c*c),l=Uc(u),h=u&&-l/u;Iu+=h*o,Ru+=h*s,Fu+=h*c,Au+=l,Ou+=l*(Yu+(Yu=r)),Bu+=l*(zu+(zu=i)),Lu+=l*(Uu+(Uu=a)),il(Yu,zu,Uu)}function dl(t){Su=Au=Mu=Nu=Du=Ou=Bu=Lu=Iu=Ru=Fu=0,Zc(t,nl);var e=Iu,n=Ru,r=Fu,i=e*e+n*n+r*r;return ikc?t+Math.round(-t/Cc)*Cc:t,e]}function ml(t,e,n){return(t%=Cc)?e||n?yl(bl(t),_l(e,n)):bl(t):e||n?_l(e,n):gl}function vl(t){return function(e,n){return[(e+=t)>kc?e-Cc:e<-kc?e+Cc:e,n]}}function bl(t){var e=vl(t);return e.invert=vl(-t),e}function _l(t,e){var n=Oc(t),r=Fc(t),i=Oc(e),a=Fc(e);function o(t,e){var o=Oc(e),s=Oc(t)*o,c=Fc(t)*o,u=Fc(e),l=u*n+s*r;return[Dc(c*i-l*a,s*n-u*r),Uc(l*i+c*a)]}return o.invert=function(t,e){var o=Oc(e),s=Oc(t)*o,c=Fc(t)*o,u=Fc(e),l=u*i-c*a;return[Dc(c*i+u*a,s*n+l*r),Uc(l*n-s*r)]},o}function xl(t){function e(e){return(e=t(e[0]*Ac,e[1]*Ac))[0]*=Sc,e[1]*=Sc,e}return t=ml(t[0]*Ac,t[1]*Ac,t.length>2?t[2]*Ac:0),e.invert=function(e){return(e=t.invert(e[0]*Ac,e[1]*Ac))[0]*=Sc,e[1]*=Sc,e},e}function wl(t,e,n,r,i,a){if(n){var o=Oc(e),s=Fc(e),c=r*n;null==i?(i=e+r*Cc,a=e-c/2):(i=kl(o,i),a=kl(o,a),(r>0?ia)&&(i+=r*Cc));for(var u,l=i;r>0?l>a:l1&&e.push(e.pop().concat(e.shift()))},result:function(){var n=e;return e=[],t=null,n}}}function Cl(t,e){return Mc(t[0]-e[0])=0;--a)i.point((l=u[a])[0],l[1]);else r(f.x,f.p.x,-1,i);f=f.p}u=(f=f.o).z,d=!d}while(!f.v);i.lineEnd()}}}function Ml(t){if(e=t.length){for(var e,n,r=0,i=t[0];++r=0?1:-1,E=T*k,C=E>kc,S=y*x;if(Nl.add(Dc(S*T*Fc(E),g*w+S*Oc(E))),o+=C?k+T*Cc:k,C^d>=n^b>=n){var A=du(hu(f),hu(v));gu(A);var M=du(a,A);gu(M);var N=(C^k>=0?-1:1)*Uc(M[2]);(r>N||r===N&&(A[0]||A[1]))&&(s+=C^k>=0?1:-1)}}return(o<-1e-6||o0){for(h||(i.polygonStart(),h=!0),i.lineStart(),t=0;t1&&2&c&&f.push(f.pop().concat(f.shift())),o.push(f.filter(Ll))}return f}}function Ll(t){return t.length>1}function Il(t,e){return((t=t.x)[0]<0?t[1]-Tc-xc:Tc-t[1])-((e=e.x)[0]<0?e[1]-Tc-xc:Tc-e[1])}const Rl=Bl((function(){return!0}),(function(t){var e,n=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(a,o){var s=a>0?kc:-kc,c=Mc(a-n);Mc(c-kc)0?Tc:-Tc),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),t.point(a,r),e=0):i!==s&&c>=kc&&(Mc(n-i)xc?Nc((Fc(e)*(a=Oc(r))*Fc(n)-Fc(r)*(i=Oc(e))*Fc(t))/(i*a*o)):(e+r)/2}(n,r,a,o),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),e=0),t.point(n=a,r=o),i=s},lineEnd:function(){t.lineEnd(),n=r=NaN},clean:function(){return 2-e}}}),(function(t,e,n,r){var i;if(null==t)i=n*Tc,r.point(-kc,i),r.point(0,i),r.point(kc,i),r.point(kc,0),r.point(kc,-i),r.point(0,-i),r.point(-kc,-i),r.point(-kc,0),r.point(-kc,i);else if(Mc(t[0]-e[0])>xc){var a=t[0]0,i=Mc(e)>xc;function a(t,n){return Oc(t)*Oc(n)>e}function o(t,n,r){var i=[1,0,0],a=du(hu(t),hu(n)),o=fu(a,a),s=a[0],c=o-s*s;if(!c)return!r&&t;var u=e*o/c,l=-e*s/c,h=du(i,a),f=yu(i,u);pu(f,yu(a,l));var d=h,p=fu(f,d),y=fu(d,d),g=p*p-y*(fu(f,f)-1);if(!(g<0)){var m=jc(g),v=yu(d,(-p-m)/y);if(pu(v,f),v=lu(v),!r)return v;var b,_=t[0],x=n[0],w=t[1],k=n[1];x<_&&(b=_,_=x,x=b);var T=x-_,E=Mc(T-kc)0^v[1]<(Mc(v[0]-_)kc^(_<=v[0]&&v[0]<=x)){var C=yu(d,(-p+m)/y);return pu(C,f),[v,lu(C)]}}}function s(e,n){var i=r?t:kc-t,a=0;return e<-i?a|=1:e>i&&(a|=2),n<-i?a|=4:n>i&&(a|=8),a}return Bl(a,(function(t){var e,n,c,u,l;return{lineStart:function(){u=c=!1,l=1},point:function(h,f){var d,p=[h,f],y=a(h,f),g=r?y?0:s(h,f):y?s(h+(h<0?kc:-kc),f):0;if(!e&&(u=c=y)&&t.lineStart(),y!==c&&(!(d=o(e,p))||Cl(e,d)||Cl(p,d))&&(p[2]=1),y!==c)l=0,y?(t.lineStart(),d=o(p,e),t.point(d[0],d[1])):(d=o(e,p),t.point(d[0],d[1],2),t.lineEnd()),e=d;else if(i&&e&&r^y){var m;g&n||!(m=o(p,e,!0))||(l=0,r?(t.lineStart(),t.point(m[0][0],m[0][1]),t.point(m[1][0],m[1][1]),t.lineEnd()):(t.point(m[1][0],m[1][1]),t.lineEnd(),t.lineStart(),t.point(m[0][0],m[0][1],3)))}!y||e&&Cl(e,p)||t.point(p[0],p[1]),e=p,c=y,n=g},lineEnd:function(){c&&t.lineEnd(),e=null},clean:function(){return l|(u&&c)<<1}}}),(function(e,r,i,a){wl(a,t,n,i,e,r)}),r?[0,-t]:[-kc,t-kc])}var Pl=1e9,jl=-Pl;function Yl(t,e,n,r){function i(i,a){return t<=i&&i<=n&&e<=a&&a<=r}function a(i,a,s,u){var l=0,h=0;if(null==i||(l=o(i,s))!==(h=o(a,s))||c(i,a)<0^s>0)do{u.point(0===l||3===l?t:n,l>1?r:e)}while((l=(l+s+4)%4)!==h);else u.point(a[0],a[1])}function o(r,i){return Mc(r[0]-t)0?0:3:Mc(r[0]-n)0?2:1:Mc(r[1]-e)0?1:0:i>0?3:2}function s(t,e){return c(t.x,e.x)}function c(t,e){var n=o(t,1),r=o(e,1);return n!==r?n-r:0===n?e[1]-t[1]:1===n?t[0]-e[0]:2===n?t[1]-e[1]:e[0]-t[0]}return function(o){var c,u,l,h,f,d,p,y,g,m,v,b=o,_=El(),x={point:w,lineStart:function(){x.point=k,u&&u.push(l=[]),m=!0,g=!1,p=y=NaN},lineEnd:function(){c&&(k(h,f),d&&g&&_.rejoin(),c.push(_.result())),x.point=w,g&&b.lineEnd()},polygonStart:function(){b=_,c=[],u=[],v=!0},polygonEnd:function(){var e=function(){for(var e=0,n=0,i=u.length;nr&&(f-a)*(r-o)>(d-o)*(t-a)&&++e:d<=r&&(f-a)*(r-o)<(d-o)*(t-a)&&--e;return e}(),n=v&&e,i=(c=P(c)).length;(n||i)&&(o.polygonStart(),n&&(o.lineStart(),a(null,null,1,o),o.lineEnd()),i&&Al(c,s,e,a,o),o.polygonEnd()),b=o,c=u=l=null}};function w(t,e){i(t,e)&&b.point(t,e)}function k(a,o){var s=i(a,o);if(u&&l.push([a,o]),m)h=a,f=o,d=s,m=!1,s&&(b.lineStart(),b.point(a,o));else if(s&&g)b.point(a,o);else{var c=[p=Math.max(jl,Math.min(Pl,p)),y=Math.max(jl,Math.min(Pl,y))],_=[a=Math.max(jl,Math.min(Pl,a)),o=Math.max(jl,Math.min(Pl,o))];!function(t,e,n,r,i,a){var o,s=t[0],c=t[1],u=0,l=1,h=e[0]-s,f=e[1]-c;if(o=n-s,h||!(o>0)){if(o/=h,h<0){if(o0){if(o>l)return;o>u&&(u=o)}if(o=i-s,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>u&&(u=o)}else if(h>0){if(o0)){if(o/=f,f<0){if(o0){if(o>l)return;o>u&&(u=o)}if(o=a-c,f||!(o<0)){if(o/=f,f<0){if(o>l)return;o>u&&(u=o)}else if(f>0){if(o0&&(t[0]=s+u*h,t[1]=c+u*f),l<1&&(e[0]=s+l*h,e[1]=c+l*f),!0}}}}}(c,_,t,e,n,r)?s&&(b.lineStart(),b.point(a,o),v=!1):(g||(b.lineStart(),b.point(c[0],c[1])),b.point(_[0],_[1]),s||b.lineEnd(),v=!1)}p=a,y=o,g=s}return x}}function zl(){var t,e,n,r=0,i=0,a=960,o=500;return n={stream:function(n){return t&&e===n?t:t=Yl(r,i,a,o)(e=n)},extent:function(s){return arguments.length?(r=+s[0][0],i=+s[0][1],a=+s[1][0],o=+s[1][1],t=e=null,n):[[r,i],[a,o]]}}}var Ul,ql,Hl,$l=mc(),Wl={sphere:Hc,point:Hc,lineStart:function(){Wl.point=Gl,Wl.lineEnd=Vl},lineEnd:Hc,polygonStart:Hc,polygonEnd:Hc};function Vl(){Wl.point=Wl.lineEnd=Hc}function Gl(t,e){Ul=t*=Ac,ql=Fc(e*=Ac),Hl=Oc(e),Wl.point=Xl}function Xl(t,e){t*=Ac;var n=Fc(e*=Ac),r=Oc(e),i=Mc(t-Ul),a=Oc(i),o=r*Fc(i),s=Hl*n-ql*r*a,c=ql*n+Hl*r*a;$l.add(Dc(jc(o*o+s*s),c)),Ul=t,ql=n,Hl=r}function Zl(t){return $l.reset(),Zc(t,Wl),+$l}var Ql=[null,null],Kl={type:"LineString",coordinates:Ql};function Jl(t,e){return Ql[0]=t,Ql[1]=e,Zl(Kl)}var th={Feature:function(t,e){return nh(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r0&&(i=Jl(t[a],t[a-1]))>0&&n<=i&&r<=i&&(n+r-i)*(1-Math.pow((n-r)/i,2))xc})).map(c)).concat(k(Bc(a/d)*d,i,d).filter((function(t){return Mc(t%y)>xc})).map(u))}return m.lines=function(){return v().map((function(t){return{type:"LineString",coordinates:t}}))},m.outline=function(){return{type:"Polygon",coordinates:[l(r).concat(h(o).slice(1),l(n).reverse().slice(1),h(s).reverse().slice(1))]}},m.extent=function(t){return arguments.length?m.extentMajor(t).extentMinor(t):m.extentMinor()},m.extentMajor=function(t){return arguments.length?(r=+t[0][0],n=+t[1][0],s=+t[0][1],o=+t[1][1],r>n&&(t=r,r=n,n=t),s>o&&(t=s,s=o,o=t),m.precision(g)):[[r,s],[n,o]]},m.extentMinor=function(n){return arguments.length?(e=+n[0][0],t=+n[1][0],a=+n[0][1],i=+n[1][1],e>t&&(n=e,e=t,t=n),a>i&&(n=a,a=i,i=n),m.precision(g)):[[e,a],[t,i]]},m.step=function(t){return arguments.length?m.stepMajor(t).stepMinor(t):m.stepMinor()},m.stepMajor=function(t){return arguments.length?(p=+t[0],y=+t[1],m):[p,y]},m.stepMinor=function(t){return arguments.length?(f=+t[0],d=+t[1],m):[f,d]},m.precision=function(f){return arguments.length?(g=+f,c=uh(a,i,90),u=lh(e,t,g),l=uh(s,o,90),h=lh(r,n,g),m):g},m.extentMajor([[-180,-89.999999],[180,89.999999]]).extentMinor([[-180,-80.000001],[180,80.000001]])}function fh(){return hh()()}function dh(t,e){var n=t[0]*Ac,r=t[1]*Ac,i=e[0]*Ac,a=e[1]*Ac,o=Oc(r),s=Fc(r),c=Oc(a),u=Fc(a),l=o*Oc(n),h=o*Fc(n),f=c*Oc(i),d=c*Fc(i),p=2*Uc(jc(qc(a-r)+o*c*qc(i-n))),y=Fc(p),g=p?function(t){var e=Fc(t*=p)/y,n=Fc(p-t)/y,r=n*l+e*f,i=n*h+e*d,a=n*s+e*u;return[Dc(i,r)*Sc,Dc(a,jc(r*r+i*i))*Sc]}:function(){return[n*Sc,r*Sc]};return g.distance=p,g}function ph(t){return t}var yh,gh,mh,vh,bh=mc(),_h=mc(),xh={point:Hc,lineStart:Hc,lineEnd:Hc,polygonStart:function(){xh.lineStart=wh,xh.lineEnd=Eh},polygonEnd:function(){xh.lineStart=xh.lineEnd=xh.point=Hc,bh.add(Mc(_h)),_h.reset()},result:function(){var t=bh/2;return bh.reset(),t}};function wh(){xh.point=kh}function kh(t,e){xh.point=Th,yh=mh=t,gh=vh=e}function Th(t,e){_h.add(vh*t-mh*e),mh=t,vh=e}function Eh(){Th(yh,gh)}const Ch=xh;var Sh=1/0,Ah=Sh,Mh=-Sh,Nh=Mh;const Dh={point:function(t,e){tMh&&(Mh=t),eNh&&(Nh=e)},lineStart:Hc,lineEnd:Hc,polygonStart:Hc,polygonEnd:Hc,result:function(){var t=[[Sh,Ah],[Mh,Nh]];return Mh=Nh=-(Ah=Sh=1/0),t}};var Oh,Bh,Lh,Ih,Rh=0,Fh=0,Ph=0,jh=0,Yh=0,zh=0,Uh=0,qh=0,Hh=0,$h={point:Wh,lineStart:Vh,lineEnd:Zh,polygonStart:function(){$h.lineStart=Qh,$h.lineEnd=Kh},polygonEnd:function(){$h.point=Wh,$h.lineStart=Vh,$h.lineEnd=Zh},result:function(){var t=Hh?[Uh/Hh,qh/Hh]:zh?[jh/zh,Yh/zh]:Ph?[Rh/Ph,Fh/Ph]:[NaN,NaN];return Rh=Fh=Ph=jh=Yh=zh=Uh=qh=Hh=0,t}};function Wh(t,e){Rh+=t,Fh+=e,++Ph}function Vh(){$h.point=Gh}function Gh(t,e){$h.point=Xh,Wh(Lh=t,Ih=e)}function Xh(t,e){var n=t-Lh,r=e-Ih,i=jc(n*n+r*r);jh+=i*(Lh+t)/2,Yh+=i*(Ih+e)/2,zh+=i,Wh(Lh=t,Ih=e)}function Zh(){$h.point=Wh}function Qh(){$h.point=Jh}function Kh(){tf(Oh,Bh)}function Jh(t,e){$h.point=tf,Wh(Oh=Lh=t,Bh=Ih=e)}function tf(t,e){var n=t-Lh,r=e-Ih,i=jc(n*n+r*r);jh+=i*(Lh+t)/2,Yh+=i*(Ih+e)/2,zh+=i,Uh+=(i=Ih*t-Lh*e)*(Lh+t),qh+=i*(Ih+e),Hh+=3*i,Wh(Lh=t,Ih=e)}const ef=$h;function nf(t){this._context=t}nf.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,e){switch(this._point){case 0:this._context.moveTo(t,e),this._point=1;break;case 1:this._context.lineTo(t,e);break;default:this._context.moveTo(t+this._radius,e),this._context.arc(t,e,this._radius,0,Cc)}},result:Hc};var rf,af,of,sf,cf,uf=mc(),lf={point:Hc,lineStart:function(){lf.point=hf},lineEnd:function(){rf&&ff(af,of),lf.point=Hc},polygonStart:function(){rf=!0},polygonEnd:function(){rf=null},result:function(){var t=+uf;return uf.reset(),t}};function hf(t,e){lf.point=ff,af=sf=t,of=cf=e}function ff(t,e){sf-=t,cf-=e,uf.add(jc(sf*sf+cf*cf)),sf=t,cf=e}const df=lf;function pf(){this._string=[]}function yf(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function gf(t,e){var n,r,i=4.5;function a(t){return t&&("function"==typeof i&&r.pointRadius(+i.apply(this,arguments)),Zc(t,n(r))),r.result()}return a.area=function(t){return Zc(t,n(Ch)),Ch.result()},a.measure=function(t){return Zc(t,n(df)),df.result()},a.bounds=function(t){return Zc(t,n(Dh)),Dh.result()},a.centroid=function(t){return Zc(t,n(ef)),ef.result()},a.projection=function(e){return arguments.length?(n=null==e?(t=null,ph):(t=e).stream,a):t},a.context=function(t){return arguments.length?(r=null==t?(e=null,new pf):new nf(e=t),"function"!=typeof i&&r.pointRadius(i),a):e},a.pointRadius=function(t){return arguments.length?(i="function"==typeof t?t:(r.pointRadius(+t),+t),a):i},a.projection(t).context(e)}function mf(t){return{stream:vf(t)}}function vf(t){return function(e){var n=new bf;for(var r in t)n[r]=t[r];return n.stream=e,n}}function bf(){}function _f(t,e,n){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),null!=r&&t.clipExtent(null),Zc(n,t.stream(Dh)),e(Dh.result()),null!=r&&t.clipExtent(r),t}function xf(t,e,n){return _f(t,(function(n){var r=e[1][0]-e[0][0],i=e[1][1]-e[0][1],a=Math.min(r/(n[1][0]-n[0][0]),i/(n[1][1]-n[0][1])),o=+e[0][0]+(r-a*(n[1][0]+n[0][0]))/2,s=+e[0][1]+(i-a*(n[1][1]+n[0][1]))/2;t.scale(150*a).translate([o,s])}),n)}function wf(t,e,n){return xf(t,[[0,0],e],n)}function kf(t,e,n){return _f(t,(function(n){var r=+e,i=r/(n[1][0]-n[0][0]),a=(r-i*(n[1][0]+n[0][0]))/2,o=-i*n[0][1];t.scale(150*i).translate([a,o])}),n)}function Tf(t,e,n){return _f(t,(function(n){var r=+e,i=r/(n[1][1]-n[0][1]),a=-i*n[0][0],o=(r-i*(n[1][1]+n[0][1]))/2;t.scale(150*i).translate([a,o])}),n)}pf.prototype={_radius:4.5,_circle:yf(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,e){switch(this._point){case 0:this._string.push("M",t,",",e),this._point=1;break;case 1:this._string.push("L",t,",",e);break;default:null==this._circle&&(this._circle=yf(this._radius)),this._string.push("M",t,",",e,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}},bf.prototype={constructor:bf,point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var Ef=Oc(30*Ac);function Cf(t,e){return+e?function(t,e){function n(r,i,a,o,s,c,u,l,h,f,d,p,y,g){var m=u-r,v=l-i,b=m*m+v*v;if(b>4*e&&y--){var _=o+f,x=s+d,w=c+p,k=jc(_*_+x*x+w*w),T=Uc(w/=k),E=Mc(Mc(w)-1)e||Mc((m*M+v*N)/b-.5)>.3||o*f+s*d+c*p2?t[2]%360*Ac:0,M()):[g*Sc,m*Sc,v*Sc]},S.angle=function(t){return arguments.length?(b=t%360*Ac,M()):b*Sc},S.reflectX=function(t){return arguments.length?(_=t?-1:1,M()):_<0},S.reflectY=function(t){return arguments.length?(x=t?-1:1,M()):x<0},S.precision=function(t){return arguments.length?(o=Cf(s,C=t*t),N()):jc(C)},S.fitExtent=function(t,e){return xf(S,t,e)},S.fitSize=function(t,e){return wf(S,t,e)},S.fitWidth=function(t,e){return kf(S,t,e)},S.fitHeight=function(t,e){return Tf(S,t,e)},function(){return e=t.apply(this,arguments),S.invert=e.invert&&A,M()}}function Of(t){var e=0,n=kc/3,r=Df(t),i=r(e,n);return i.parallels=function(t){return arguments.length?r(e=t[0]*Ac,n=t[1]*Ac):[e*Sc,n*Sc]},i}function Bf(t,e){var n=Fc(t),r=(n+Fc(e))/2;if(Mc(r)=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?c:o).invert(t)},l.stream=function(n){return t&&e===n?t:(r=[o.stream(e=n),s.stream(n),c.stream(n)],i=r.length,t={point:function(t,e){for(var n=-1;++n0?e<-Tc+xc&&(e=-Tc+xc):e>Tc-xc&&(e=Tc-xc);var n=i/Rc(Wf(e),r);return[n*Fc(r*t),i-n*Oc(r*t)]}return a.invert=function(t,e){var n=i-e,a=Pc(r)*jc(t*t+n*n),o=Dc(t,Mc(n))*Pc(n);return n*r<0&&(o-=kc*Pc(t)*Pc(n)),[o/r,2*Nc(Rc(i/a,1/r))-Tc]},a}function Gf(){return Of(Vf).scale(109.5).parallels([30,30])}function Xf(t,e){return[t,e]}function Zf(){return Nf(Xf).scale(152.63)}function Qf(t,e){var n=Oc(t),r=t===e?Fc(t):(n-Oc(e))/(e-t),i=n/r+t;if(Mc(r)2?t[2]+90:90]):[(t=n())[0],t[1],t[2]-90]},n([0,0,90]).scale(159.155)}function md(t,e){return t.parent===e.parent?1:2}function vd(t,e){return t+e.x}function bd(t,e){return Math.max(t,e.y)}function _d(){var t=md,e=1,n=1,r=!1;function i(i){var a,o=0;i.eachAfter((function(e){var n=e.children;n?(e.x=function(t){return t.reduce(vd,0)/t.length}(n),e.y=function(t){return 1+t.reduce(bd,0)}(n)):(e.x=a?o+=t(e,a):0,e.y=0,a=e)}));var s=function(t){for(var e;e=t.children;)t=e[0];return t}(i),c=function(t){for(var e;e=t.children;)t=e[e.length-1];return t}(i),u=s.x-t(s,c)/2,l=c.x+t(c,s)/2;return i.eachAfter(r?function(t){t.x=(t.x-i.x)*e,t.y=(i.y-t.y)*n}:function(t){t.x=(t.x-u)/(l-u)*e,t.y=(1-(i.y?t.y/i.y:1))*n})}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i}function xd(t){var e=0,n=t.children,r=n&&n.length;if(r)for(;--r>=0;)e+=n[r].value;else e=1;t.value=e}function wd(t,e){var n,r,i,a,o,s=new Cd(t),c=+t.value&&(s.value=t.value),u=[s];for(null==e&&(e=kd);n=u.pop();)if(c&&(n.value=+n.data.value),(i=e(n.data))&&(o=i.length))for(n.children=new Array(o),a=o-1;a>=0;--a)u.push(r=n.children[a]=new Cd(i[a])),r.parent=n,r.depth=n.depth+1;return s.eachBefore(Ed)}function kd(t){return t.children}function Td(t){t.data=t.data.data}function Ed(t){var e=0;do{t.height=e}while((t=t.parent)&&t.height<++e)}function Cd(t){this.data=t,this.depth=this.height=0,this.parent=null}id.invert=function(t,e){for(var n,r=e,i=r*r,a=i*i*i,o=0;o<12&&(a=(i=(r-=n=(r*(Jf+td*i+a*(ed+nd*i))-e)/(Jf+3*td*i+a*(7*ed+9*nd*i)))*r)*i*i,!(Mc(n)xc&&--i>0);return[t/(.8707+(a=r*r)*(a*(a*a*a*(.003971-.001529*a)-.013791)-.131979)),r]},hd.invert=Pf(Uc),dd.invert=Pf((function(t){return 2*Nc(t)})),yd.invert=function(t,e){return[-e,2*Nc(Lc(t))-Tc]},Cd.prototype=wd.prototype={constructor:Cd,count:function(){return this.eachAfter(xd)},each:function(t){var e,n,r,i,a=this,o=[a];do{for(e=o.reverse(),o=[];a=e.pop();)if(t(a),n=a.children)for(r=0,i=n.length;r=0;--n)i.push(e[n]);return this},sum:function(t){return this.eachAfter((function(e){for(var n=+t(e.data)||0,r=e.children,i=r&&r.length;--i>=0;)n+=r[i].value;e.value=n}))},sort:function(t){return this.eachBefore((function(e){e.children&&e.children.sort(t)}))},path:function(t){for(var e=this,n=function(t,e){if(t===e)return t;var n=t.ancestors(),r=e.ancestors(),i=null;for(t=n.pop(),e=r.pop();t===e;)i=t,t=n.pop(),e=r.pop();return i}(e,t),r=[e];e!==n;)e=e.parent,r.push(e);for(var i=r.length;t!==n;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e},descendants:function(){var t=[];return this.each((function(e){t.push(e)})),t},leaves:function(){var t=[];return this.eachBefore((function(e){e.children||t.push(e)})),t},links:function(){var t=this,e=[];return t.each((function(n){n!==t&&e.push({source:n.parent,target:n})})),e},copy:function(){return wd(this).eachBefore(Td)}};var Sd=Array.prototype.slice;function Ad(t){for(var e,n,r=0,i=(t=function(t){for(var e,n,r=t.length;r;)n=Math.random()*r--|0,e=t[r],t[r]=t[n],t[n]=e;return t}(Sd.call(t))).length,a=[];r0&&n*n>r*r+i*i}function Od(t,e){for(var n=0;n(o*=o)?(r=(u+o-i)/(2*u),a=Math.sqrt(Math.max(0,o/u-r*r)),n.x=t.x-r*s-a*c,n.y=t.y-r*c+a*s):(r=(u+i-o)/(2*u),a=Math.sqrt(Math.max(0,i/u-r*r)),n.x=e.x+r*s-a*c,n.y=e.y+r*c+a*s)):(n.x=e.x+n.r,n.y=e.y)}function Fd(t,e){var n=t.r+e.r-1e-6,r=e.x-t.x,i=e.y-t.y;return n>0&&n*n>r*r+i*i}function Pd(t){var e=t._,n=t.next._,r=e.r+n.r,i=(e.x*n.r+n.x*e.r)/r,a=(e.y*n.r+n.y*e.r)/r;return i*i+a*a}function jd(t){this._=t,this.next=null,this.previous=null}function Yd(t){if(!(i=t.length))return 0;var e,n,r,i,a,o,s,c,u,l,h;if((e=t[0]).x=0,e.y=0,!(i>1))return e.r;if(n=t[1],e.x=-n.r,n.x=e.r,n.y=0,!(i>2))return e.r+n.r;Rd(n,e,r=t[2]),e=new jd(e),n=new jd(n),r=new jd(r),e.next=r.previous=n,n.next=e.previous=r,r.next=n.previous=e;t:for(s=3;s0)throw new Error("cycle");return a}return n.id=function(e){return arguments.length?(t=qd(e),n):t},n.parentId=function(t){return arguments.length?(e=qd(t),n):e},n}function ap(t,e){return t.parent===e.parent?1:2}function op(t){var e=t.children;return e?e[0]:t.t}function sp(t){var e=t.children;return e?e[e.length-1]:t.t}function cp(t,e,n){var r=n/(e.i-t.i);e.c-=r,e.s+=n,t.c+=r,e.z+=n,e.m+=n}function up(t,e,n){return t.a.parent===e.parent?t.a:n}function lp(t,e){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=e}function hp(){var t=ap,e=1,n=1,r=null;function i(i){var c=function(t){for(var e,n,r,i,a,o=new lp(t,0),s=[o];e=s.pop();)if(r=e._.children)for(e.children=new Array(a=r.length),i=a-1;i>=0;--i)s.push(n=e.children[i]=new lp(r[i],i)),n.parent=e;return(o.parent=new lp(null,0)).children=[o],o}(i);if(c.eachAfter(a),c.parent.m=-c.z,c.eachBefore(o),r)i.eachBefore(s);else{var u=i,l=i,h=i;i.eachBefore((function(t){t.xl.x&&(l=t),t.depth>h.depth&&(h=t)}));var f=u===l?1:t(u,l)/2,d=f-u.x,p=e/(l.x+f+d),y=n/(h.depth||1);i.eachBefore((function(t){t.x=(t.x+d)*p,t.y=t.depth*y}))}return i}function a(e){var n=e.children,r=e.parent.children,i=e.i?r[e.i-1]:null;if(n){!function(t){for(var e,n=0,r=0,i=t.children,a=i.length;--a>=0;)(e=i[a]).z+=n,e.m+=n,n+=e.s+(r+=e.c)}(e);var a=(n[0].z+n[n.length-1].z)/2;i?(e.z=i.z+t(e._,i._),e.m=e.z-a):e.z=a}else i&&(e.z=i.z+t(e._,i._));e.parent.A=function(e,n,r){if(n){for(var i,a=e,o=e,s=n,c=a.parent.children[0],u=a.m,l=o.m,h=s.m,f=c.m;s=sp(s),a=op(a),s&&a;)c=op(c),(o=sp(o)).a=e,(i=s.z+h-a.z-u+t(s._,a._))>0&&(cp(up(s,e,r),e,i),u+=i,l+=i),h+=s.m,u+=a.m,f+=c.m,l+=o.m;s&&!sp(o)&&(o.t=s,o.m+=h-l),a&&!op(c)&&(c.t=a,c.m+=u-f,r=e)}return r}(e,i,e.parent.A||r[0])}function o(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function s(t){t.x*=e,t.y=t.depth*n}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i}function fp(t,e,n,r,i){for(var a,o=t.children,s=-1,c=o.length,u=t.value&&(i-n)/t.value;++sf&&(f=s),g=l*l*y,(d=Math.max(f/g,g/h))>p){l-=s;break}p=d}m.push(o={value:l,dice:c1?e:1)},n}(dp);function gp(){var t=yp,e=!1,n=1,r=1,i=[0],a=Hd,o=Hd,s=Hd,c=Hd,u=Hd;function l(t){return t.x0=t.y0=0,t.x1=n,t.y1=r,t.eachBefore(h),i=[0],e&&t.eachBefore(Qd),t}function h(e){var n=i[e.depth],r=e.x0+n,l=e.y0+n,h=e.x1-n,f=e.y1-n;h=n-1){var l=s[e];return l.x0=i,l.y0=a,l.x1=o,void(l.y1=c)}for(var h=u[e],f=r/2+h,d=e+1,p=n-1;d>>1;u[y]c-a){var v=(i*m+o*g)/r;t(e,d,g,i,a,v,c),t(d,n,m,v,a,o,c)}else{var b=(a*m+c*g)/r;t(e,d,g,i,a,o,b),t(d,n,m,i,b,o,c)}}(0,c,t.value,e,n,r,i)}function vp(t,e,n,r,i){(1&t.depth?fp:Kd)(t,e,n,r,i)}const bp=function t(e){function n(t,n,r,i,a){if((o=t._squarify)&&o.ratio===e)for(var o,s,c,u,l,h=-1,f=o.length,d=t.value;++h1?e:1)},n}(dp);function _p(t){var e=t.length;return function(n){return t[Math.max(0,Math.min(e-1,Math.floor(n*e)))]}}function xp(t,e){var n=fn(+t,+e);return function(t){var e=n(t);return e-360*Math.floor(e/360)}}function wp(t,e){return t=+t,e=+e,function(n){return Math.round(t*(1-n)+e*n)}}var kp=Math.SQRT2;function Tp(t){return((t=Math.exp(t))+1/t)/2}function Ep(t,e){var n,r,i=t[0],a=t[1],o=t[2],s=e[0],c=e[1],u=e[2],l=s-i,h=c-a,f=l*l+h*h;if(f<1e-12)r=Math.log(u/o)/kp,n=function(t){return[i+t*l,a+t*h,o*Math.exp(kp*t*r)]};else{var d=Math.sqrt(f),p=(u*u-o*o+4*f)/(2*o*2*d),y=(u*u-o*o-4*f)/(2*u*2*d),g=Math.log(Math.sqrt(p*p+1)-p),m=Math.log(Math.sqrt(y*y+1)-y);r=(m-g)/kp,n=function(t){var e,n=t*r,s=Tp(g),c=o/(2*d)*(s*(e=kp*n+g,((e=Math.exp(2*e))-1)/(e+1))-function(t){return((t=Math.exp(t))-1/t)/2}(g));return[i+c*l,a+c*h,o*s/Tp(kp*n+g)]}}return n.duration=1e3*r,n}function Cp(t){return function(e,n){var r=t((e=rn(e)).h,(n=rn(n)).h),i=dn(e.s,n.s),a=dn(e.l,n.l),o=dn(e.opacity,n.opacity);return function(t){return e.h=r(t),e.s=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const Sp=Cp(fn);var Ap=Cp(dn);function Mp(t,e){var n=dn((t=ba(t)).l,(e=ba(e)).l),r=dn(t.a,e.a),i=dn(t.b,e.b),a=dn(t.opacity,e.opacity);return function(e){return t.l=n(e),t.a=r(e),t.b=i(e),t.opacity=a(e),t+""}}function Np(t){return function(e,n){var r=t((e=Sa(e)).h,(n=Sa(n)).h),i=dn(e.c,n.c),a=dn(e.l,n.l),o=dn(e.opacity,n.opacity);return function(t){return e.h=r(t),e.c=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const Dp=Np(fn);var Op=Np(dn);function Bp(t){return function e(n){function r(e,r){var i=t((e=Pa(e)).h,(r=Pa(r)).h),a=dn(e.s,r.s),o=dn(e.l,r.l),s=dn(e.opacity,r.opacity);return function(t){return e.h=i(t),e.s=a(t),e.l=o(Math.pow(t,n)),e.opacity=s(t),e+""}}return n=+n,r.gamma=e,r}(1)}const Lp=Bp(fn);var Ip=Bp(dn);function Rp(t,e){for(var n=0,r=e.length-1,i=e[0],a=new Array(r<0?0:r);n1&&Yp(t[n[r-2]],t[n[r-1]],t[i])<=0;)--r;n[r++]=i}return n.slice(0,r)}function qp(t){if((n=t.length)<3)return null;var e,n,r=new Array(n),i=new Array(n);for(e=0;e=0;--e)u.push(t[r[a[e]][2]]);for(e=+s;es!=u>s&&o<(c-n)*(s-r)/(u-r)+n&&(l=!l),c=n,u=r;return l}function $p(t){for(var e,n,r=-1,i=t.length,a=t[i-1],o=a[0],s=a[1],c=0;++r1);return t+n*a*Math.sqrt(-2*Math.log(i)/i)}}return n.source=t,n}(Wp),Xp=function t(e){function n(){var t=Gp.source(e).apply(this,arguments);return function(){return Math.exp(t())}}return n.source=t,n}(Wp),Zp=function t(e){function n(t){return function(){for(var n=0,r=0;rr&&(e=n,n=r,r=e),function(t){return Math.max(n,Math.min(r,t))}}function py(t,e,n){var r=t[0],i=t[1],a=e[0],o=e[1];return i2?yy:py,i=a=null,h}function h(e){return isNaN(e=+e)?n:(i||(i=r(o.map(t),s,c)))(t(u(e)))}return h.invert=function(n){return u(e((a||(a=r(s,o.map(t),kn)))(n)))},h.domain=function(t){return arguments.length?(o=ny.call(t,uy),u===hy||(u=dy(o)),l()):o.slice()},h.range=function(t){return arguments.length?(s=ry.call(t),l()):s.slice()},h.rangeRound=function(t){return s=ry.call(t),c=wp,l()},h.clamp=function(t){return arguments.length?(u=t?dy(o):hy,h):u!==hy},h.interpolate=function(t){return arguments.length?(c=t,l()):c},h.unknown=function(t){return arguments.length?(n=t,h):n},function(n,r){return t=n,e=r,l()}}function vy(t,e){return my()(t,e)}function by(t,e,n,r){var i,a=M(t,e,n);switch((r=nc(null==r?",f":r)).type){case"s":var o=Math.max(Math.abs(t),Math.abs(e));return null!=r.precision||isNaN(i=yc(a,o))||(r.precision=i),uc(r,o);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=gc(a,Math.max(Math.abs(t),Math.abs(e))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=pc(a))||(r.precision=i-2*("%"===r.type))}return cc(r)}function _y(t){var e=t.domain;return t.ticks=function(t){var n=e();return S(n[0],n[n.length-1],null==t?10:t)},t.tickFormat=function(t,n){var r=e();return by(r[0],r[r.length-1],null==t?10:t,n)},t.nice=function(n){null==n&&(n=10);var r,i=e(),a=0,o=i.length-1,s=i[a],c=i[o];return c0?r=A(s=Math.floor(s/r)*r,c=Math.ceil(c/r)*r,n):r<0&&(r=A(s=Math.ceil(s*r)/r,c=Math.floor(c*r)/r,n)),r>0?(i[a]=Math.floor(s/r)*r,i[o]=Math.ceil(c/r)*r,e(i)):r<0&&(i[a]=Math.ceil(s*r)/r,i[o]=Math.floor(c*r)/r,e(i)),t},t}function xy(){var t=vy(hy,hy);return t.copy=function(){return gy(t,xy())},Jp.apply(t,arguments),_y(t)}function wy(t){var e;function n(t){return isNaN(t=+t)?e:t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=ny.call(e,uy),n):t.slice()},n.unknown=function(t){return arguments.length?(e=t,n):e},n.copy=function(){return wy(t).unknown(e)},t=arguments.length?ny.call(t,uy):[0,1],_y(n)}function ky(t,e){var n,r=0,i=(t=t.slice()).length-1,a=t[r],o=t[i];return o0){for(;fc)break;y.push(h)}}else for(;f=1;--l)if(!((h=u*l)c)break;y.push(h)}}else y=S(f,d,Math.min(d-f,p)).map(n);return r?y.reverse():y},r.tickFormat=function(t,i){if(null==i&&(i=10===a?".0e":","),"function"!=typeof i&&(i=cc(i)),t===1/0)return i;null==t&&(t=10);var o=Math.max(1,a*t/r.ticks().length);return function(t){var r=t/n(Math.round(e(t)));return r*a0?r[i-1]:e[0],i=r?[i[r-1],n]:[i[o-1],i[o]]},o.unknown=function(e){return arguments.length?(t=e,o):o},o.thresholds=function(){return i.slice()},o.copy=function(){return qy().domain([e,n]).range(a).unknown(t)},Jp.apply(_y(o),arguments)}function Hy(){var t,e=[.5],n=[0,1],r=1;function i(i){return i<=i?n[u(e,i,0,r)]:t}return i.domain=function(t){return arguments.length?(e=ry.call(t),r=Math.min(e.length,n.length-1),i):e.slice()},i.range=function(t){return arguments.length?(n=ry.call(t),r=Math.min(e.length,n.length-1),i):n.slice()},i.invertExtent=function(t){var r=n.indexOf(t);return[e[r-1],e[r]]},i.unknown=function(e){return arguments.length?(t=e,i):t},i.copy=function(){return Hy().domain(e).range(n).unknown(t)},Jp.apply(i,arguments)}var $y=new Date,Wy=new Date;function Vy(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return $y.setTime(+e),Wy.setTime(+r),t($y),t(Wy),Math.floor(n($y,Wy))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var Gy=Vy((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Gy.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Vy((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const Xy=Gy;var Zy=Gy.range,Qy=Vy((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()}));const Ky=Qy;var Jy=Qy.range,tg=6e4,eg=36e5,ng=6048e5;function rg(t){return Vy((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*tg)/ng}))}var ig=rg(0),ag=rg(1),og=rg(2),sg=rg(3),cg=rg(4),ug=rg(5),lg=rg(6),hg=ig.range,fg=ag.range,dg=og.range,pg=sg.range,yg=cg.range,gg=ug.range,mg=lg.range,vg=Vy((function(t){t.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*tg)/864e5}),(function(t){return t.getDate()-1}));const bg=vg;var _g=vg.range,xg=Vy((function(t){t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds()-t.getMinutes()*tg)}),(function(t,e){t.setTime(+t+e*eg)}),(function(t,e){return(e-t)/eg}),(function(t){return t.getHours()}));const wg=xg;var kg=xg.range,Tg=Vy((function(t){t.setTime(t-t.getMilliseconds()-1e3*t.getSeconds())}),(function(t,e){t.setTime(+t+e*tg)}),(function(t,e){return(e-t)/tg}),(function(t){return t.getMinutes()}));const Eg=Tg;var Cg=Tg.range,Sg=Vy((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+1e3*e)}),(function(t,e){return(e-t)/1e3}),(function(t){return t.getUTCSeconds()}));const Ag=Sg;var Mg=Sg.range,Ng=Vy((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t}));Ng.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Vy((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):Ng:null};const Dg=Ng;var Og=Ng.range;function Bg(t){return Vy((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/ng}))}var Lg=Bg(0),Ig=Bg(1),Rg=Bg(2),Fg=Bg(3),Pg=Bg(4),jg=Bg(5),Yg=Bg(6),zg=Lg.range,Ug=Ig.range,qg=Rg.range,Hg=Fg.range,$g=Pg.range,Wg=jg.range,Vg=Yg.range,Gg=Vy((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/864e5}),(function(t){return t.getUTCDate()-1}));const Xg=Gg;var Zg=Gg.range,Qg=Vy((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));Qg.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Vy((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const Kg=Qg;var Jg=Qg.range;function tm(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function em(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function nm(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}function rm(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=ym(i),l=gm(i),h=ym(a),f=gm(a),d=ym(o),p=gm(o),y=ym(s),g=gm(s),m=ym(c),v=gm(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:Fm,e:Fm,f:Um,g:Jm,G:ev,H:Pm,I:jm,j:Ym,L:zm,m:qm,M:Hm,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:Tv,s:Ev,S:$m,u:Wm,U:Vm,V:Xm,w:Zm,W:Qm,x:null,X:null,y:Km,Y:tv,Z:nv,"%":kv},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:rv,e:rv,f:cv,g:bv,G:xv,H:iv,I:av,j:ov,L:sv,m:uv,M:lv,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:Tv,s:Ev,S:hv,u:fv,U:dv,V:yv,w:gv,W:mv,x:null,X:null,y:vv,Y:_v,Z:wv,"%":kv},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p[r[0].toLowerCase()],n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f[r[0].toLowerCase()],n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v[r[0].toLowerCase()],n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g[r[0].toLowerCase()],n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Sm,e:Sm,f:Bm,g:km,G:wm,H:Mm,I:Mm,j:Am,L:Om,m:Cm,M:Nm,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l[r[0].toLowerCase()],n+r[0].length):-1},q:Em,Q:Im,s:Rm,S:Dm,u:vm,U:bm,V:_m,w:mm,W:xm,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:km,Y:wm,Z:Tm,"%":Lm};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=em(nm(a.y,0,1))).getUTCDay(),r=i>4||0===i?Ig.ceil(r):Ig(r),r=Xg.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=tm(nm(a.y,0,1))).getDay(),r=i>4||0===i?ag.ceil(r):ag(r),r=bg.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?em(nm(a.y,0,1)).getUTCDay():tm(nm(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,em(a)):tm(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in um?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}var im,am,om,sm,cm,um={"-":"",_:" ",0:"0"},lm=/^\s*\d+/,hm=/^%/,fm=/[\\^$*+?|[\]().{}]/g;function dm(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a68?1900:2e3),n+r[0].length):-1}function Tm(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Em(t,e,n){var r=lm.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function Cm(t,e,n){var r=lm.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Sm(t,e,n){var r=lm.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Am(t,e,n){var r=lm.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Mm(t,e,n){var r=lm.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Nm(t,e,n){var r=lm.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Dm(t,e,n){var r=lm.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Om(t,e,n){var r=lm.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Bm(t,e,n){var r=lm.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Lm(t,e,n){var r=hm.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Im(t,e,n){var r=lm.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Rm(t,e,n){var r=lm.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Fm(t,e){return dm(t.getDate(),e,2)}function Pm(t,e){return dm(t.getHours(),e,2)}function jm(t,e){return dm(t.getHours()%12||12,e,2)}function Ym(t,e){return dm(1+bg.count(Xy(t),t),e,3)}function zm(t,e){return dm(t.getMilliseconds(),e,3)}function Um(t,e){return zm(t,e)+"000"}function qm(t,e){return dm(t.getMonth()+1,e,2)}function Hm(t,e){return dm(t.getMinutes(),e,2)}function $m(t,e){return dm(t.getSeconds(),e,2)}function Wm(t){var e=t.getDay();return 0===e?7:e}function Vm(t,e){return dm(ig.count(Xy(t)-1,t),e,2)}function Gm(t){var e=t.getDay();return e>=4||0===e?cg(t):cg.ceil(t)}function Xm(t,e){return t=Gm(t),dm(cg.count(Xy(t),t)+(4===Xy(t).getDay()),e,2)}function Zm(t){return t.getDay()}function Qm(t,e){return dm(ag.count(Xy(t)-1,t),e,2)}function Km(t,e){return dm(t.getFullYear()%100,e,2)}function Jm(t,e){return dm((t=Gm(t)).getFullYear()%100,e,2)}function tv(t,e){return dm(t.getFullYear()%1e4,e,4)}function ev(t,e){var n=t.getDay();return dm((t=n>=4||0===n?cg(t):cg.ceil(t)).getFullYear()%1e4,e,4)}function nv(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+dm(e/60|0,"0",2)+dm(e%60,"0",2)}function rv(t,e){return dm(t.getUTCDate(),e,2)}function iv(t,e){return dm(t.getUTCHours(),e,2)}function av(t,e){return dm(t.getUTCHours()%12||12,e,2)}function ov(t,e){return dm(1+Xg.count(Kg(t),t),e,3)}function sv(t,e){return dm(t.getUTCMilliseconds(),e,3)}function cv(t,e){return sv(t,e)+"000"}function uv(t,e){return dm(t.getUTCMonth()+1,e,2)}function lv(t,e){return dm(t.getUTCMinutes(),e,2)}function hv(t,e){return dm(t.getUTCSeconds(),e,2)}function fv(t){var e=t.getUTCDay();return 0===e?7:e}function dv(t,e){return dm(Lg.count(Kg(t)-1,t),e,2)}function pv(t){var e=t.getUTCDay();return e>=4||0===e?Pg(t):Pg.ceil(t)}function yv(t,e){return t=pv(t),dm(Pg.count(Kg(t),t)+(4===Kg(t).getUTCDay()),e,2)}function gv(t){return t.getUTCDay()}function mv(t,e){return dm(Ig.count(Kg(t)-1,t),e,2)}function vv(t,e){return dm(t.getUTCFullYear()%100,e,2)}function bv(t,e){return dm((t=pv(t)).getUTCFullYear()%100,e,2)}function _v(t,e){return dm(t.getUTCFullYear()%1e4,e,4)}function xv(t,e){var n=t.getUTCDay();return dm((t=n>=4||0===n?Pg(t):Pg.ceil(t)).getUTCFullYear()%1e4,e,4)}function wv(){return"+0000"}function kv(){return"%"}function Tv(t){return+t}function Ev(t){return Math.floor(+t/1e3)}function Cv(t){return im=rm(t),am=im.format,om=im.parse,sm=im.utcFormat,cm=im.utcParse,im}Cv({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Sv=31536e6;function Av(t){return new Date(t)}function Mv(t){return t instanceof Date?+t:+new Date(+t)}function Nv(t,e,n,r,i,o,s,c,u){var l=vy(hy,hy),h=l.invert,f=l.domain,d=u(".%L"),p=u(":%S"),y=u("%I:%M"),g=u("%I %p"),m=u("%a %d"),v=u("%b %d"),b=u("%B"),_=u("%Y"),x=[[s,1,1e3],[s,5,5e3],[s,15,15e3],[s,30,3e4],[o,1,6e4],[o,5,3e5],[o,15,9e5],[o,30,18e5],[i,1,36e5],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,864e5],[r,2,1728e5],[n,1,6048e5],[e,1,2592e6],[e,3,7776e6],[t,1,Sv]];function w(a){return(s(a)1)&&(t-=Math.floor(t));var e=Math.abs(t-.5);return v_.h=360*t-100,v_.s=1.5-1.5*e,v_.l=.8-.9*e,v_+""}var __=Ze(),x_=Math.PI/3,w_=2*Math.PI/3;function k_(t){var e;return t=(.5-t)*Math.PI,__.r=255*(e=Math.sin(t))*e,__.g=255*(e=Math.sin(t+x_))*e,__.b=255*(e=Math.sin(t+w_))*e,__+""}function T_(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+t*(1172.33-t*(10793.56-t*(33300.12-t*(38394.49-14825.05*t)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+t*(557.33+t*(1225.33-t*(3574.96-t*(1073.77+707.56*t)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+t*(3211.1-t*(15327.97-t*(27814-t*(22569.18-6838.66*t)))))))+")"}function E_(t){var e=t.length;return function(n){return t[Math.max(0,Math.min(e-1,Math.floor(n*e)))]}}const C_=E_(nb("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));var S_=E_(nb("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),A_=E_(nb("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),M_=E_(nb("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));function N_(t){return Te(ie(t).call(document.documentElement))}var D_=0;function O_(){return new B_}function B_(){this._="@"+(++D_).toString(36)}function L_(t){return"string"==typeof t?new xe([document.querySelectorAll(t)],[document.documentElement]):new xe([null==t?[]:t],_e)}function I_(t,e){null==e&&(e=Mn().touches);for(var n=0,r=e?e.length:0,i=new Array(r);n1?0:t<-1?$_:Math.acos(t)}function X_(t){return t>=1?W_:t<=-1?-W_:Math.asin(t)}function Z_(t){return t.innerRadius}function Q_(t){return t.outerRadius}function K_(t){return t.startAngle}function J_(t){return t.endAngle}function tx(t){return t&&t.padAngle}function ex(t,e,n,r,i,a,o,s){var c=n-t,u=r-e,l=o-i,h=s-a,f=h*c-l*u;if(!(f*fN*N+D*D&&(T=C,E=S),{cx:T,cy:E,x01:-l,y01:-h,x11:T*(i/x-1),y11:E*(i/x-1)}}function rx(){var t=Z_,e=Q_,n=R_(0),r=null,i=K_,a=J_,o=tx,s=null;function c(){var c,u,l=+t.apply(this,arguments),h=+e.apply(this,arguments),f=i.apply(this,arguments)-W_,d=a.apply(this,arguments)-W_,p=F_(d-f),y=d>f;if(s||(s=c=$i()),hH_)if(p>V_-H_)s.moveTo(h*j_(f),h*U_(f)),s.arc(0,0,h,f,d,!y),l>H_&&(s.moveTo(l*j_(d),l*U_(d)),s.arc(0,0,l,d,f,y));else{var g,m,v=f,b=d,_=f,x=d,w=p,k=p,T=o.apply(this,arguments)/2,E=T>H_&&(r?+r.apply(this,arguments):q_(l*l+h*h)),C=z_(F_(h-l)/2,+n.apply(this,arguments)),S=C,A=C;if(E>H_){var M=X_(E/l*U_(T)),N=X_(E/h*U_(T));(w-=2*M)>H_?(_+=M*=y?1:-1,x-=M):(w=0,_=x=(f+d)/2),(k-=2*N)>H_?(v+=N*=y?1:-1,b-=N):(k=0,v=b=(f+d)/2)}var D=h*j_(v),O=h*U_(v),B=l*j_(x),L=l*U_(x);if(C>H_){var I,R=h*j_(b),F=h*U_(b),P=l*j_(_),j=l*U_(_);if(p<$_&&(I=ex(D,O,P,j,R,F,B,L))){var Y=D-I[0],z=O-I[1],U=R-I[0],q=F-I[1],H=1/U_(G_((Y*U+z*q)/(q_(Y*Y+z*z)*q_(U*U+q*q)))/2),$=q_(I[0]*I[0]+I[1]*I[1]);S=z_(C,(l-$)/(H-1)),A=z_(C,(h-$)/(H+1))}}k>H_?A>H_?(g=nx(P,j,D,O,h,A,y),m=nx(R,F,B,L,h,A,y),s.moveTo(g.cx+g.x01,g.cy+g.y01),AH_&&w>H_?S>H_?(g=nx(B,L,R,F,l,-S,y),m=nx(D,O,P,j,l,-S,y),s.lineTo(g.cx+g.x01,g.cy+g.y01),S=l;--h)s.point(g[h],m[h]);s.lineEnd(),s.areaEnd()}y&&(g[u]=+t(f,u,c),m[u]=+n(f,u,c),s.point(e?+e(f,u,c):g[u],r?+r(f,u,c):m[u]))}if(d)return s=null,d+""||null}function u(){return cx().defined(i).curve(o).context(a)}return c.x=function(n){return arguments.length?(t="function"==typeof n?n:R_(+n),e=null,c):t},c.x0=function(e){return arguments.length?(t="function"==typeof e?e:R_(+e),c):t},c.x1=function(t){return arguments.length?(e=null==t?null:"function"==typeof t?t:R_(+t),c):e},c.y=function(t){return arguments.length?(n="function"==typeof t?t:R_(+t),r=null,c):n},c.y0=function(t){return arguments.length?(n="function"==typeof t?t:R_(+t),c):n},c.y1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:R_(+t),c):r},c.lineX0=c.lineY0=function(){return u().x(t).y(n)},c.lineY1=function(){return u().x(t).y(r)},c.lineX1=function(){return u().x(e).y(n)},c.defined=function(t){return arguments.length?(i="function"==typeof t?t:R_(!!t),c):i},c.curve=function(t){return arguments.length?(o=t,null!=a&&(s=o(a)),c):o},c.context=function(t){return arguments.length?(null==t?a=s=null:s=o(a=t),c):a},c}function lx(t,e){return et?1:e>=t?0:NaN}function hx(t){return t}function fx(){var t=hx,e=lx,n=null,r=R_(0),i=R_(V_),a=R_(0);function o(o){var s,c,u,l,h,f=o.length,d=0,p=new Array(f),y=new Array(f),g=+r.apply(this,arguments),m=Math.min(V_,Math.max(-V_,i.apply(this,arguments)-g)),v=Math.min(Math.abs(m)/f,a.apply(this,arguments)),b=v*(m<0?-1:1);for(s=0;s0&&(d+=h);for(null!=e?p.sort((function(t,n){return e(y[t],y[n])})):null!=n&&p.sort((function(t,e){return n(o[t],o[e])})),s=0,u=d?(m-f*b)/d:0;s0?h*u:0)+b,y[c]={data:o[c],index:s,value:h,startAngle:g,endAngle:l,padAngle:v};return y}return o.value=function(e){return arguments.length?(t="function"==typeof e?e:R_(+e),o):t},o.sortValues=function(t){return arguments.length?(e=t,n=null,o):e},o.sort=function(t){return arguments.length?(n=t,e=null,o):n},o.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:R_(+t),o):r},o.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:R_(+t),o):i},o.padAngle=function(t){return arguments.length?(a="function"==typeof t?t:R_(+t),o):a},o}ix.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}};var dx=yx(ax);function px(t){this._curve=t}function yx(t){function e(e){return new px(t(e))}return e._curve=t,e}function gx(t){var e=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?e(yx(t)):e()._curve},t}function mx(){return gx(cx().curve(dx))}function vx(){var t=ux().curve(dx),e=t.curve,n=t.lineX0,r=t.lineX1,i=t.lineY0,a=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return gx(n())},delete t.lineX0,t.lineEndAngle=function(){return gx(r())},delete t.lineX1,t.lineInnerRadius=function(){return gx(i())},delete t.lineY0,t.lineOuterRadius=function(){return gx(a())},delete t.lineY1,t.curve=function(t){return arguments.length?e(yx(t)):e()._curve},t}function bx(t,e){return[(e=+e)*Math.cos(t-=Math.PI/2),e*Math.sin(t)]}px.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,e){this._curve.point(e*Math.sin(t),e*-Math.cos(t))}};var _x=Array.prototype.slice;function xx(t){return t.source}function wx(t){return t.target}function kx(t){var e=xx,n=wx,r=ox,i=sx,a=null;function o(){var o,s=_x.call(arguments),c=e.apply(this,s),u=n.apply(this,s);if(a||(a=o=$i()),t(a,+r.apply(this,(s[0]=c,s)),+i.apply(this,s),+r.apply(this,(s[0]=u,s)),+i.apply(this,s)),o)return a=null,o+""||null}return o.source=function(t){return arguments.length?(e=t,o):e},o.target=function(t){return arguments.length?(n=t,o):n},o.x=function(t){return arguments.length?(r="function"==typeof t?t:R_(+t),o):r},o.y=function(t){return arguments.length?(i="function"==typeof t?t:R_(+t),o):i},o.context=function(t){return arguments.length?(a=null==t?null:t,o):a},o}function Tx(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e=(e+r)/2,n,e,i,r,i)}function Ex(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e,n=(n+i)/2,r,n,r,i)}function Cx(t,e,n,r,i){var a=bx(e,n),o=bx(e,n=(n+i)/2),s=bx(r,n),c=bx(r,i);t.moveTo(a[0],a[1]),t.bezierCurveTo(o[0],o[1],s[0],s[1],c[0],c[1])}function Sx(){return kx(Tx)}function Ax(){return kx(Ex)}function Mx(){var t=kx(Cx);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t}const Nx={draw:function(t,e){var n=Math.sqrt(e/$_);t.moveTo(n,0),t.arc(0,0,n,0,V_)}},Dx={draw:function(t,e){var n=Math.sqrt(e/5)/2;t.moveTo(-3*n,-n),t.lineTo(-n,-n),t.lineTo(-n,-3*n),t.lineTo(n,-3*n),t.lineTo(n,-n),t.lineTo(3*n,-n),t.lineTo(3*n,n),t.lineTo(n,n),t.lineTo(n,3*n),t.lineTo(-n,3*n),t.lineTo(-n,n),t.lineTo(-3*n,n),t.closePath()}};var Ox=Math.sqrt(1/3),Bx=2*Ox;const Lx={draw:function(t,e){var n=Math.sqrt(e/Bx),r=n*Ox;t.moveTo(0,-n),t.lineTo(r,0),t.lineTo(0,n),t.lineTo(-r,0),t.closePath()}};var Ix=Math.sin($_/10)/Math.sin(7*$_/10),Rx=Math.sin(V_/10)*Ix,Fx=-Math.cos(V_/10)*Ix;const Px={draw:function(t,e){var n=Math.sqrt(.8908130915292852*e),r=Rx*n,i=Fx*n;t.moveTo(0,-n),t.lineTo(r,i);for(var a=1;a<5;++a){var o=V_*a/5,s=Math.cos(o),c=Math.sin(o);t.lineTo(c*n,-s*n),t.lineTo(s*r-c*i,c*r+s*i)}t.closePath()}},jx={draw:function(t,e){var n=Math.sqrt(e),r=-n/2;t.rect(r,r,n,n)}};var Yx=Math.sqrt(3);const zx={draw:function(t,e){var n=-Math.sqrt(e/(3*Yx));t.moveTo(0,2*n),t.lineTo(-Yx*n,-n),t.lineTo(Yx*n,-n),t.closePath()}};var Ux=-.5,qx=Math.sqrt(3)/2,Hx=1/Math.sqrt(12),$x=3*(Hx/2+1);const Wx={draw:function(t,e){var n=Math.sqrt(e/$x),r=n/2,i=n*Hx,a=r,o=n*Hx+n,s=-a,c=o;t.moveTo(r,i),t.lineTo(a,o),t.lineTo(s,c),t.lineTo(Ux*r-qx*i,qx*r+Ux*i),t.lineTo(Ux*a-qx*o,qx*a+Ux*o),t.lineTo(Ux*s-qx*c,qx*s+Ux*c),t.lineTo(Ux*r+qx*i,Ux*i-qx*r),t.lineTo(Ux*a+qx*o,Ux*o-qx*a),t.lineTo(Ux*s+qx*c,Ux*c-qx*s),t.closePath()}};var Vx=[Nx,Dx,Lx,jx,Px,zx,Wx];function Gx(){var t=R_(Nx),e=R_(64),n=null;function r(){var r;if(n||(n=r=$i()),t.apply(this,arguments).draw(n,+e.apply(this,arguments)),r)return n=null,r+""||null}return r.type=function(e){return arguments.length?(t="function"==typeof e?e:R_(e),r):t},r.size=function(t){return arguments.length?(e="function"==typeof t?t:R_(+t),r):e},r.context=function(t){return arguments.length?(n=null==t?null:t,r):n},r}function Xx(){}function Zx(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function Qx(t){this._context=t}function Kx(t){return new Qx(t)}function Jx(t){this._context=t}function tw(t){return new Jx(t)}function ew(t){this._context=t}function nw(t){return new ew(t)}function rw(t,e){this._basis=new Qx(t),this._beta=e}Qx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Zx(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Zx(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Jx.prototype={areaStart:Xx,areaEnd:Xx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:Zx(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},ew.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:Zx(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},rw.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,e=this._y,n=t.length-1;if(n>0)for(var r,i=t[0],a=e[0],o=t[n]-i,s=e[n]-a,c=-1;++c<=n;)r=c/n,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*o),this._beta*e[c]+(1-this._beta)*(a+r*s));this._x=this._y=null,this._basis.lineEnd()},point:function(t,e){this._x.push(+t),this._y.push(+e)}};const iw=function t(e){function n(t){return 1===e?new Qx(t):new rw(t,e)}return n.beta=function(e){return t(+e)},n}(.85);function aw(t,e,n){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-e),t._y2+t._k*(t._y1-n),t._x2,t._y2)}function ow(t,e){this._context=t,this._k=(1-e)/6}ow.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:aw(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2,this._x1=t,this._y1=e;break;case 2:this._point=3;default:aw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const sw=function t(e){function n(t){return new ow(t,e)}return n.tension=function(e){return t(+e)},n}(0);function cw(t,e){this._context=t,this._k=(1-e)/6}cw.prototype={areaStart:Xx,areaEnd:Xx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:aw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const uw=function t(e){function n(t){return new cw(t,e)}return n.tension=function(e){return t(+e)},n}(0);function lw(t,e){this._context=t,this._k=(1-e)/6}lw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:aw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const hw=function t(e){function n(t){return new lw(t,e)}return n.tension=function(e){return t(+e)},n}(0);function fw(t,e,n){var r=t._x1,i=t._y1,a=t._x2,o=t._y2;if(t._l01_a>H_){var s=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*s-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*s-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>H_){var u=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,l=3*t._l23_a*(t._l23_a+t._l12_a);a=(a*u+t._x1*t._l23_2a-e*t._l12_2a)/l,o=(o*u+t._y1*t._l23_2a-n*t._l12_2a)/l}t._context.bezierCurveTo(r,i,a,o,t._x2,t._y2)}function dw(t,e){this._context=t,this._alpha=e}dw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3;default:fw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const pw=function t(e){function n(t){return e?new dw(t,e):new ow(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function yw(t,e){this._context=t,this._alpha=e}yw.prototype={areaStart:Xx,areaEnd:Xx,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:fw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const gw=function t(e){function n(t){return e?new yw(t,e):new cw(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function mw(t,e){this._context=t,this._alpha=e}mw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:fw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const vw=function t(e){function n(t){return e?new mw(t,e):new lw(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function bw(t){this._context=t}function _w(t){return new bw(t)}function xw(t){return t<0?-1:1}function ww(t,e,n){var r=t._x1-t._x0,i=e-t._x1,a=(t._y1-t._y0)/(r||i<0&&-0),o=(n-t._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(xw(a)+xw(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function kw(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function Tw(t,e,n){var r=t._x0,i=t._y0,a=t._x1,o=t._y1,s=(a-r)/3;t._context.bezierCurveTo(r+s,i+s*e,a-s,o-s*n,a,o)}function Ew(t){this._context=t}function Cw(t){this._context=new Sw(t)}function Sw(t){this._context=t}function Aw(t){return new Ew(t)}function Mw(t){return new Cw(t)}function Nw(t){this._context=t}function Dw(t){var e,n,r=t.length-1,i=new Array(r),a=new Array(r),o=new Array(r);for(i[0]=0,a[0]=2,o[0]=t[0]+2*t[1],e=1;e=0;--e)i[e]=(o[e]-i[e+1])/a[e];for(a[r-1]=(t[r]+i[r-1])/2,e=0;e1)for(var n,r,i,a=1,o=t[e[0]],s=o.length;a=0;)n[e]=e;return n}function jw(t,e){return t[e]}function Yw(){var t=R_([]),e=Pw,n=Fw,r=jw;function i(i){var a,o,s=t.apply(this,arguments),c=i.length,u=s.length,l=new Array(u);for(a=0;a0){for(var n,r,i,a=0,o=t[0].length;a0)for(var n,r,i,a,o,s,c=0,u=t[e[0]].length;c0?(r[0]=a,r[1]=a+=i):i<0?(r[1]=o,r[0]=o+=i):(r[0]=0,r[1]=i)}function qw(t,e){if((n=t.length)>0){for(var n,r=0,i=t[e[0]],a=i.length;r0&&(r=(n=t[e[0]]).length)>0){for(var n,r,i,a=0,o=1;oa&&(a=e,r=n);return r}function Vw(t){var e=t.map(Gw);return Pw(t).sort((function(t,n){return e[t]-e[n]}))}function Gw(t){for(var e,n=0,r=-1,i=t.length;++r=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};var Kw="%Y-%m-%dT%H:%M:%S.%LZ";const Jw=Date.prototype.toISOString?function(t){return t.toISOString()}:sm(Kw),tk=+new Date("2000-01-01T00:00:00.000Z")?function(t){var e=new Date(t);return isNaN(e)?null:e}:cm(Kw);function ek(t,e,n){var r=new $n,i=e;return null==e?(r.restart(t,e,n),r):(e=+e,n=null==n?qn():+n,r.restart((function a(o){o+=i,r.restart(a,i+=e,n),t(o)}),e,n),r)}function nk(t){return function(){return t}}function rk(t){return t[0]}function ik(t){return t[1]}function ak(){this._=null}function ok(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function sk(t,e){var n=e,r=e.R,i=n.U;i?i.L===n?i.L=r:i.R=r:t._=r,r.U=i,n.U=r,n.R=r.L,n.R&&(n.R.U=n),r.L=n}function ck(t,e){var n=e,r=e.L,i=n.U;i?i.L===n?i.L=r:i.R=r:t._=r,r.U=i,n.U=r,n.L=r.R,n.L&&(n.L.U=n),r.R=n}function uk(t){for(;t.L;)t=t.L;return t}ak.prototype={constructor:ak,insert:function(t,e){var n,r,i;if(t){if(e.P=t,e.N=t.N,t.N&&(t.N.P=e),t.N=e,t.R){for(t=t.R;t.L;)t=t.L;t.L=e}else t.R=e;n=t}else this._?(t=uk(this._),e.P=null,e.N=t,t.P=t.L=e,n=t):(e.P=e.N=null,this._=e,n=null);for(e.L=e.R=null,e.U=n,e.C=!0,t=e;n&&n.C;)n===(r=n.U).L?(i=r.R)&&i.C?(n.C=i.C=!1,r.C=!0,t=r):(t===n.R&&(sk(this,n),n=(t=n).U),n.C=!1,r.C=!0,ck(this,r)):(i=r.L)&&i.C?(n.C=i.C=!1,r.C=!0,t=r):(t===n.L&&(ck(this,n),n=(t=n).U),n.C=!1,r.C=!0,sk(this,r)),n=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var e,n,r,i=t.U,a=t.L,o=t.R;if(n=a?o?uk(o):a:o,i?i.L===t?i.L=n:i.R=n:this._=n,a&&o?(r=n.C,n.C=t.C,n.L=a,a.U=n,n!==o?(i=n.U,n.U=t.U,t=n.R,i.L=t,n.R=o,o.U=n):(n.U=i,i=n,t=n.R)):(r=t.C,t=n),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((e=i.R).C&&(e.C=!1,i.C=!0,sk(this,i),e=i.R),e.L&&e.L.C||e.R&&e.R.C){e.R&&e.R.C||(e.L.C=!1,e.C=!0,ck(this,e),e=i.R),e.C=i.C,i.C=e.R.C=!1,sk(this,i),t=this._;break}}else if((e=i.L).C&&(e.C=!1,i.C=!0,ck(this,i),e=i.L),e.L&&e.L.C||e.R&&e.R.C){e.L&&e.L.C||(e.R.C=!1,e.C=!0,sk(this,e),e=i.L),e.C=i.C,i.C=e.L.C=!1,ck(this,i),t=this._;break}e.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};const lk=ak;function hk(t,e,n,r){var i=[null,null],a=Ik.push(i)-1;return i.left=t,i.right=e,n&&dk(i,t,e,n),r&&dk(i,e,t,r),Bk[t.index].halfedges.push(a),Bk[e.index].halfedges.push(a),i}function fk(t,e,n){var r=[e,n];return r.left=t,r}function dk(t,e,n,r){t[0]||t[1]?t.left===n?t[1]=r:t[0]=r:(t[0]=r,t.left=e,t.right=n)}function pk(t,e,n,r,i){var a,o=t[0],s=t[1],c=o[0],u=o[1],l=0,h=1,f=s[0]-c,d=s[1]-u;if(a=e-c,f||!(a>0)){if(a/=f,f<0){if(a0){if(a>h)return;a>l&&(l=a)}if(a=r-c,f||!(a<0)){if(a/=f,f<0){if(a>h)return;a>l&&(l=a)}else if(f>0){if(a0)){if(a/=d,d<0){if(a0){if(a>h)return;a>l&&(l=a)}if(a=i-u,d||!(a<0)){if(a/=d,d<0){if(a>h)return;a>l&&(l=a)}else if(d>0){if(a0||h<1)||(l>0&&(t[0]=[c+l*f,u+l*d]),h<1&&(t[1]=[c+h*f,u+h*d]),!0)}}}}}function yk(t,e,n,r,i){var a=t[1];if(a)return!0;var o,s,c=t[0],u=t.left,l=t.right,h=u[0],f=u[1],d=l[0],p=l[1],y=(h+d)/2,g=(f+p)/2;if(p===f){if(y=r)return;if(h>d){if(c){if(c[1]>=i)return}else c=[y,n];a=[y,i]}else{if(c){if(c[1]1)if(h>d){if(c){if(c[1]>=i)return}else c=[(n-s)/o,n];a=[(i-s)/o,i]}else{if(c){if(c[1]=r)return}else c=[e,o*e+s];a=[r,o*r+s]}else{if(c){if(c[0]=-Fk)){var d=c*c+u*u,p=l*l+h*h,y=(h*d-u*p)/f,g=(c*p-l*d)/f,m=_k.pop()||new xk;m.arc=t,m.site=i,m.x=y+o,m.y=(m.cy=g+s)+Math.sqrt(y*y+g*g),t.circle=m;for(var v=null,b=Lk._;b;)if(m.yRk)s=s.L;else{if(!((i=a-Dk(s,o))>Rk)){r>-Rk?(e=s.P,n=s):i>-Rk?(e=s,n=s.N):e=n=s;break}if(!s.R){e=s;break}s=s.R}!function(t){Bk[t.index]={site:t,halfedges:[]}}(t);var c=Ck(t);if(Ok.insert(e,c),e||n){if(e===n)return kk(e),n=Ck(e.site),Ok.insert(c,n),c.edge=n.edge=hk(e.site,c.site),wk(e),void wk(n);if(n){kk(e),kk(n);var u=e.site,l=u[0],h=u[1],f=t[0]-l,d=t[1]-h,p=n.site,y=p[0]-l,g=p[1]-h,m=2*(f*g-d*y),v=f*f+d*d,b=y*y+g*g,_=[(g*v-d*b)/m+l,(f*b-y*v)/m+h];dk(n.edge,u,p,_),c.edge=hk(u,t,null,_),n.edge=hk(t,p,null,_),wk(e),wk(n)}else c.edge=hk(e.site,c.site)}}function Nk(t,e){var n=t.site,r=n[0],i=n[1],a=i-e;if(!a)return r;var o=t.P;if(!o)return-1/0;var s=(n=o.site)[0],c=n[1],u=c-e;if(!u)return s;var l=s-r,h=1/a-1/u,f=l/u;return h?(-f+Math.sqrt(f*f-2*h*(l*l/(-2*u)-c+u/2+i-a/2)))/h+r:(r+s)/2}function Dk(t,e){var n=t.N;if(n)return Nk(n,e);var r=t.site;return r[1]===e?r[0]:1/0}var Ok,Bk,Lk,Ik,Rk=1e-6,Fk=1e-12;function Pk(t,e,n){return(t[0]-n[0])*(e[1]-t[1])-(t[0]-e[0])*(n[1]-t[1])}function jk(t,e){return e[1]-t[1]||e[0]-t[0]}function Yk(t,e){var n,r,i,a=t.sort(jk).pop();for(Ik=[],Bk=new Array(t.length),Ok=new lk,Lk=new lk;;)if(i=bk,a&&(!i||a[1]Rk||Math.abs(i[0][1]-i[1][1])>Rk)||delete Ik[a]}(o,s,c,u),function(t,e,n,r){var i,a,o,s,c,u,l,h,f,d,p,y,g=Bk.length,m=!0;for(i=0;iRk||Math.abs(y-f)>Rk)&&(c.splice(s,0,Ik.push(fk(o,d,Math.abs(p-t)Rk?[t,Math.abs(h-t)Rk?[Math.abs(f-r)Rk?[n,Math.abs(h-n)Rk?[Math.abs(f-e)=s)return null;var c=t-i.site[0],u=e-i.site[1],l=c*c+u*u;do{i=a.cells[r=o],o=null,i.halfedges.forEach((function(n){var r=a.edges[n],s=r.left;if(s!==i.site&&s||(s=r.right)){var c=t-s[0],u=e-s[1],h=c*c+u*u;hr?(r+i)/2:Math.min(0,r)||Math.max(0,i),o>a?(a+o)/2:Math.min(0,a)||Math.max(0,o))}function eT(){var t,e,n=Xk,r=Zk,i=tT,a=Kk,o=Jk,s=[0,1/0],c=[[-1/0,-1/0],[1/0,1/0]],u=250,l=Ep,h=ft("start","zoom","end"),f=500,d=0;function p(t){t.property("__zoom",Qk).on("wheel.zoom",x).on("mousedown.zoom",w).on("dblclick.zoom",k).filter(o).on("touchstart.zoom",T).on("touchmove.zoom",E).on("touchend.zoom touchcancel.zoom",C).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function y(t,e){return(e=Math.max(s[0],Math.min(s[1],e)))===t.k?t:new Hk(e,t.x,t.y)}function g(t,e,n){var r=e[0]-n[0]*t.k,i=e[1]-n[1]*t.k;return r===t.x&&i===t.y?t:new Hk(t.k,r,i)}function m(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function v(t,e,n){t.on("start.zoom",(function(){b(this,arguments).start()})).on("interrupt.zoom end.zoom",(function(){b(this,arguments).end()})).tween("zoom",(function(){var t=this,i=arguments,a=b(t,i),o=r.apply(t,i),s=null==n?m(o):"function"==typeof n?n.apply(t,i):n,c=Math.max(o[1][0]-o[0][0],o[1][1]-o[0][1]),u=t.__zoom,h="function"==typeof e?e.apply(t,i):e,f=l(u.invert(s).concat(c/u.k),h.invert(s).concat(c/h.k));return function(t){if(1===t)t=h;else{var e=f(t),n=c/e[2];t=new Hk(n,s[0]-e[0]*n,s[1]-e[1]*n)}a.zoom(null,t)}}))}function b(t,e,n){return!n&&t.__zooming||new _(t,e)}function _(t,e){this.that=t,this.args=e,this.active=0,this.extent=r.apply(t,e),this.taps=0}function x(){if(n.apply(this,arguments)){var t=b(this,arguments),e=this.__zoom,r=Math.max(s[0],Math.min(s[1],e.k*Math.pow(2,a.apply(this,arguments)))),o=On(this);if(t.wheel)t.mouse[0][0]===o[0]&&t.mouse[0][1]===o[1]||(t.mouse[1]=e.invert(t.mouse[0]=o)),clearTimeout(t.wheel);else{if(e.k===r)return;t.mouse=[o,e.invert(o)],ir(this),t.start()}Gk(),t.wheel=setTimeout(u,150),t.zoom("mouse",i(g(y(e,r),t.mouse[0],t.mouse[1]),t.extent,c))}function u(){t.wheel=null,t.end()}}function w(){if(!e&&n.apply(this,arguments)){var t=b(this,arguments,!0),r=Te(le.view).on("mousemove.zoom",u,!0).on("mouseup.zoom",l,!0),a=On(this),o=le.clientX,s=le.clientY;Se(le.view),Vk(),t.mouse=[a,this.__zoom.invert(a)],ir(this),t.start()}function u(){if(Gk(),!t.moved){var e=le.clientX-o,n=le.clientY-s;t.moved=e*e+n*n>d}t.zoom("mouse",i(g(t.that.__zoom,t.mouse[0]=On(t.that),t.mouse[1]),t.extent,c))}function l(){r.on("mousemove.zoom mouseup.zoom",null),Ae(le.view,t.moved),Gk(),t.end()}}function k(){if(n.apply(this,arguments)){var t=this.__zoom,e=On(this),a=t.invert(e),o=t.k*(le.shiftKey?.5:2),s=i(g(y(t,o),e,a),r.apply(this,arguments),c);Gk(),u>0?Te(this).transition().duration(u).call(v,s,e):Te(this).call(p.transform,s)}}function T(){if(n.apply(this,arguments)){var e,r,i,a,o=le.touches,s=o.length,c=b(this,arguments,le.changedTouches.length===s);for(Vk(),r=0;r{t.exports={graphlib:n(574),layout:n(8123),debug:n(7570),util:{time:n(1138).time,notime:n(1138).notime},version:n(8177)}},1207:(t,e,n)=>{"use strict";var r=n(8436),i=n(4079);t.exports={run:function(t){var e="greedy"===t.graph().acyclicer?i(t,function(t){return function(e){return t.edge(e).weight}}(t)):function(t){var e=[],n={},i={};return r.forEach(t.nodes(),(function a(o){r.has(i,o)||(i[o]=!0,n[o]=!0,r.forEach(t.outEdges(o),(function(t){r.has(n,t.w)?e.push(t):a(t.w)})),delete n[o])})),e}(t);r.forEach(e,(function(e){var n=t.edge(e);t.removeEdge(e),n.forwardName=e.name,n.reversed=!0,t.setEdge(e.w,e.v,n,r.uniqueId("rev"))}))},undo:function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.reversed){t.removeEdge(e);var r=n.forwardName;delete n.reversed,delete n.forwardName,t.setEdge(e.w,e.v,n,r)}}))}}},1133:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n,r,a,o){var s={width:0,height:0,rank:o,borderType:e},c=a[e][o-1],u=i.addDummyNode(t,"border",s,n);a[e][o]=u,t.setParent(u,r),c&&t.setEdge(c,u,{weight:1})}t.exports=function(t){r.forEach(t.children(),(function e(n){var i=t.children(n),o=t.node(n);if(i.length&&r.forEach(i,e),r.has(o,"minRank")){o.borderLeft=[],o.borderRight=[];for(var s=o.minRank,c=o.maxRank+1;s{"use strict";var r=n(8436);function i(t){r.forEach(t.nodes(),(function(e){a(t.node(e))})),r.forEach(t.edges(),(function(e){a(t.edge(e))}))}function a(t){var e=t.width;t.width=t.height,t.height=e}function o(t){t.y=-t.y}function s(t){var e=t.x;t.x=t.y,t.y=e}t.exports={adjust:function(t){var e=t.graph().rankdir.toLowerCase();"lr"!==e&&"rl"!==e||i(t)},undo:function(t){var e=t.graph().rankdir.toLowerCase();"bt"!==e&&"rl"!==e||function(t){r.forEach(t.nodes(),(function(e){o(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.forEach(n.points,o),r.has(n,"y")&&o(n)}))}(t),"lr"!==e&&"rl"!==e||(function(t){r.forEach(t.nodes(),(function(e){s(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.forEach(n.points,s),r.has(n,"x")&&s(n)}))}(t),i(t))}}},7822:t=>{function e(){var t={};t._next=t._prev=t,this._sentinel=t}function n(t){t._prev._next=t._next,t._next._prev=t._prev,delete t._next,delete t._prev}function r(t,e){if("_next"!==t&&"_prev"!==t)return e}t.exports=e,e.prototype.dequeue=function(){var t=this._sentinel,e=t._prev;if(e!==t)return n(e),e},e.prototype.enqueue=function(t){var e=this._sentinel;t._prev&&t._next&&n(t),t._next=e._next,e._next._prev=t,e._next=t,t._prev=e},e.prototype.toString=function(){for(var t=[],e=this._sentinel,n=e._prev;n!==e;)t.push(JSON.stringify(n,r)),n=n._prev;return"["+t.join(", ")+"]"}},7570:(t,e,n)=>{var r=n(8436),i=n(1138),a=n(574).Graph;t.exports={debugOrdering:function(t){var e=i.buildLayerMatrix(t),n=new a({compound:!0,multigraph:!0}).setGraph({});return r.forEach(t.nodes(),(function(e){n.setNode(e,{label:e}),n.setParent(e,"layer"+t.node(e).rank)})),r.forEach(t.edges(),(function(t){n.setEdge(t.v,t.w,{},t.name)})),r.forEach(e,(function(t,e){var i="layer"+e;n.setNode(i,{rank:"same"}),r.reduce(t,(function(t,e){return n.setEdge(t,e,{style:"invis"}),e}))})),n}}},574:(t,e,n)=>{var r;try{r=n(8282)}catch(t){}r||(r=window.graphlib),t.exports=r},4079:(t,e,n)=>{var r=n(8436),i=n(574).Graph,a=n(7822);t.exports=function(t,e){if(t.nodeCount()<=1)return[];var n=function(t,e){var n=new i,o=0,s=0;r.forEach(t.nodes(),(function(t){n.setNode(t,{v:t,in:0,out:0})})),r.forEach(t.edges(),(function(t){var r=n.edge(t.v,t.w)||0,i=e(t),a=r+i;n.setEdge(t.v,t.w,a),s=Math.max(s,n.node(t.v).out+=i),o=Math.max(o,n.node(t.w).in+=i)}));var u=r.range(s+o+3).map((function(){return new a})),l=o+1;return r.forEach(n.nodes(),(function(t){c(u,l,n.node(t))})),{graph:n,buckets:u,zeroIdx:l}}(t,e||o),u=function(t,e,n){for(var r,i=[],a=e[e.length-1],o=e[0];t.nodeCount();){for(;r=o.dequeue();)s(t,e,n,r);for(;r=a.dequeue();)s(t,e,n,r);if(t.nodeCount())for(var c=e.length-2;c>0;--c)if(r=e[c].dequeue()){i=i.concat(s(t,e,n,r,!0));break}}return i}(n.graph,n.buckets,n.zeroIdx);return r.flatten(r.map(u,(function(e){return t.outEdges(e.v,e.w)})),!0)};var o=r.constant(1);function s(t,e,n,i,a){var o=a?[]:void 0;return r.forEach(t.inEdges(i.v),(function(r){var i=t.edge(r),s=t.node(r.v);a&&o.push({v:r.v,w:r.w}),s.out-=i,c(e,n,s)})),r.forEach(t.outEdges(i.v),(function(r){var i=t.edge(r),a=r.w,o=t.node(a);o.in-=i,c(e,n,o)})),t.removeNode(i.v),o}function c(t,e,n){n.out?n.in?t[n.out-n.in+e].enqueue(n):t[t.length-1].enqueue(n):t[0].enqueue(n)}},8123:(t,e,n)=>{"use strict";var r=n(8436),i=n(1207),a=n(5995),o=n(8093),s=n(1138).normalizeRanks,c=n(4219),u=n(1138).removeEmptyRanks,l=n(2981),h=n(1133),f=n(3258),d=n(3408),p=n(7873),y=n(1138),g=n(574).Graph;t.exports=function(t,e){var n=e&&e.debugTiming?y.time:y.notime;n("layout",(function(){var e=n(" buildLayoutGraph",(function(){return function(t){var e=new g({multigraph:!0,compound:!0}),n=C(t.graph());return e.setGraph(r.merge({},v,E(n,m),r.pick(n,b))),r.forEach(t.nodes(),(function(n){var i=C(t.node(n));e.setNode(n,r.defaults(E(i,_),x)),e.setParent(n,t.parent(n))})),r.forEach(t.edges(),(function(n){var i=C(t.edge(n));e.setEdge(n,r.merge({},k,E(i,w),r.pick(i,T)))})),e}(t)}));n(" runLayout",(function(){!function(t,e){e(" makeSpaceForEdgeLabels",(function(){!function(t){var e=t.graph();e.ranksep/=2,r.forEach(t.edges(),(function(n){var r=t.edge(n);r.minlen*=2,"c"!==r.labelpos.toLowerCase()&&("TB"===e.rankdir||"BT"===e.rankdir?r.width+=r.labeloffset:r.height+=r.labeloffset)}))}(t)})),e(" removeSelfEdges",(function(){!function(t){r.forEach(t.edges(),(function(e){if(e.v===e.w){var n=t.node(e.v);n.selfEdges||(n.selfEdges=[]),n.selfEdges.push({e:e,label:t.edge(e)}),t.removeEdge(e)}}))}(t)})),e(" acyclic",(function(){i.run(t)})),e(" nestingGraph.run",(function(){l.run(t)})),e(" rank",(function(){o(y.asNonCompoundGraph(t))})),e(" injectEdgeLabelProxies",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.width&&n.height){var r=t.node(e.v),i={rank:(t.node(e.w).rank-r.rank)/2+r.rank,e:e};y.addDummyNode(t,"edge-proxy",i,"_ep")}}))}(t)})),e(" removeEmptyRanks",(function(){u(t)})),e(" nestingGraph.cleanup",(function(){l.cleanup(t)})),e(" normalizeRanks",(function(){s(t)})),e(" assignRankMinMax",(function(){!function(t){var e=0;r.forEach(t.nodes(),(function(n){var i=t.node(n);i.borderTop&&(i.minRank=t.node(i.borderTop).rank,i.maxRank=t.node(i.borderBottom).rank,e=r.max(e,i.maxRank))})),t.graph().maxRank=e}(t)})),e(" removeEdgeLabelProxies",(function(){!function(t){r.forEach(t.nodes(),(function(e){var n=t.node(e);"edge-proxy"===n.dummy&&(t.edge(n.e).labelRank=n.rank,t.removeNode(e))}))}(t)})),e(" normalize.run",(function(){a.run(t)})),e(" parentDummyChains",(function(){c(t)})),e(" addBorderSegments",(function(){h(t)})),e(" order",(function(){d(t)})),e(" insertSelfEdges",(function(){!function(t){var e=y.buildLayerMatrix(t);r.forEach(e,(function(e){var n=0;r.forEach(e,(function(e,i){var a=t.node(e);a.order=i+n,r.forEach(a.selfEdges,(function(e){y.addDummyNode(t,"selfedge",{width:e.label.width,height:e.label.height,rank:a.rank,order:i+ ++n,e:e.e,label:e.label},"_se")})),delete a.selfEdges}))}))}(t)})),e(" adjustCoordinateSystem",(function(){f.adjust(t)})),e(" position",(function(){p(t)})),e(" positionSelfEdges",(function(){!function(t){r.forEach(t.nodes(),(function(e){var n=t.node(e);if("selfedge"===n.dummy){var r=t.node(n.e.v),i=r.x+r.width/2,a=r.y,o=n.x-i,s=r.height/2;t.setEdge(n.e,n.label),t.removeNode(e),n.label.points=[{x:i+2*o/3,y:a-s},{x:i+5*o/6,y:a-s},{x:i+o,y:a},{x:i+5*o/6,y:a+s},{x:i+2*o/3,y:a+s}],n.label.x=n.x,n.label.y=n.y}}))}(t)})),e(" removeBorderNodes",(function(){!function(t){r.forEach(t.nodes(),(function(e){if(t.children(e).length){var n=t.node(e),i=t.node(n.borderTop),a=t.node(n.borderBottom),o=t.node(r.last(n.borderLeft)),s=t.node(r.last(n.borderRight));n.width=Math.abs(s.x-o.x),n.height=Math.abs(a.y-i.y),n.x=o.x+n.width/2,n.y=i.y+n.height/2}})),r.forEach(t.nodes(),(function(e){"border"===t.node(e).dummy&&t.removeNode(e)}))}(t)})),e(" normalize.undo",(function(){a.undo(t)})),e(" fixupEdgeLabelCoords",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(r.has(n,"x"))switch("l"!==n.labelpos&&"r"!==n.labelpos||(n.width-=n.labeloffset),n.labelpos){case"l":n.x-=n.width/2+n.labeloffset;break;case"r":n.x+=n.width/2+n.labeloffset}}))}(t)})),e(" undoCoordinateSystem",(function(){f.undo(t)})),e(" translateGraph",(function(){!function(t){var e=Number.POSITIVE_INFINITY,n=0,i=Number.POSITIVE_INFINITY,a=0,o=t.graph(),s=o.marginx||0,c=o.marginy||0;function u(t){var r=t.x,o=t.y,s=t.width,c=t.height;e=Math.min(e,r-s/2),n=Math.max(n,r+s/2),i=Math.min(i,o-c/2),a=Math.max(a,o+c/2)}r.forEach(t.nodes(),(function(e){u(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.has(n,"x")&&u(n)})),e-=s,i-=c,r.forEach(t.nodes(),(function(n){var r=t.node(n);r.x-=e,r.y-=i})),r.forEach(t.edges(),(function(n){var a=t.edge(n);r.forEach(a.points,(function(t){t.x-=e,t.y-=i})),r.has(a,"x")&&(a.x-=e),r.has(a,"y")&&(a.y-=i)})),o.width=n-e+s,o.height=a-i+c}(t)})),e(" assignNodeIntersects",(function(){!function(t){r.forEach(t.edges(),(function(e){var n,r,i=t.edge(e),a=t.node(e.v),o=t.node(e.w);i.points?(n=i.points[0],r=i.points[i.points.length-1]):(i.points=[],n=o,r=a),i.points.unshift(y.intersectRect(a,n)),i.points.push(y.intersectRect(o,r))}))}(t)})),e(" reversePoints",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);n.reversed&&n.points.reverse()}))}(t)})),e(" acyclic.undo",(function(){i.undo(t)}))}(e,n)})),n(" updateInputGraph",(function(){!function(t,e){r.forEach(t.nodes(),(function(n){var r=t.node(n),i=e.node(n);r&&(r.x=i.x,r.y=i.y,e.children(n).length&&(r.width=i.width,r.height=i.height))})),r.forEach(t.edges(),(function(n){var i=t.edge(n),a=e.edge(n);i.points=a.points,r.has(a,"x")&&(i.x=a.x,i.y=a.y)})),t.graph().width=e.graph().width,t.graph().height=e.graph().height}(t,e)}))}))};var m=["nodesep","edgesep","ranksep","marginx","marginy"],v={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},b=["acyclicer","ranker","rankdir","align"],_=["width","height"],x={width:0,height:0},w=["minlen","weight","width","height","labeloffset"],k={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},T=["labelpos"];function E(t,e){return r.mapValues(r.pick(t,e),Number)}function C(t){var e={};return r.forEach(t,(function(t,n){e[n.toLowerCase()]=t})),e}},8436:(t,e,n)=>{var r;try{r={cloneDeep:n(361),constant:n(5703),defaults:n(1747),each:n(6073),filter:n(3105),find:n(3311),flatten:n(5564),forEach:n(4486),forIn:n(2620),has:n(8721),isUndefined:n(2353),last:n(928),map:n(5161),mapValues:n(6604),max:n(6162),merge:n(3857),min:n(3632),minBy:n(2762),now:n(7771),pick:n(9722),range:n(6026),reduce:n(4061),sortBy:n(9734),uniqueId:n(3955),values:n(2628),zipObject:n(7287)}}catch(t){}r||(r=window._),t.exports=r},2981:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n,o,s,c,u){var l=t.children(u);if(l.length){var h=i.addBorderNode(t,"_bt"),f=i.addBorderNode(t,"_bb"),d=t.node(u);t.setParent(h,u),d.borderTop=h,t.setParent(f,u),d.borderBottom=f,r.forEach(l,(function(r){a(t,e,n,o,s,c,r);var i=t.node(r),l=i.borderTop?i.borderTop:r,d=i.borderBottom?i.borderBottom:r,p=i.borderTop?o:2*o,y=l!==d?1:s-c[u]+1;t.setEdge(h,l,{weight:p,minlen:y,nestingEdge:!0}),t.setEdge(d,f,{weight:p,minlen:y,nestingEdge:!0})})),t.parent(u)||t.setEdge(e,h,{weight:0,minlen:s+c[u]})}else u!==e&&t.setEdge(e,u,{weight:0,minlen:n})}t.exports={run:function(t){var e=i.addDummyNode(t,"root",{},"_root"),n=function(t){var e={};function n(i,a){var o=t.children(i);o&&o.length&&r.forEach(o,(function(t){n(t,a+1)})),e[i]=a}return r.forEach(t.children(),(function(t){n(t,1)})),e}(t),o=r.max(r.values(n))-1,s=2*o+1;t.graph().nestingRoot=e,r.forEach(t.edges(),(function(e){t.edge(e).minlen*=s}));var c=function(t){return r.reduce(t.edges(),(function(e,n){return e+t.edge(n).weight}),0)}(t)+1;r.forEach(t.children(),(function(r){a(t,e,s,c,o,n,r)})),t.graph().nodeRankFactor=s},cleanup:function(t){var e=t.graph();t.removeNode(e.nestingRoot),delete e.nestingRoot,r.forEach(t.edges(),(function(e){t.edge(e).nestingEdge&&t.removeEdge(e)}))}}},5995:(t,e,n)=>{"use strict";var r=n(8436),i=n(1138);t.exports={run:function(t){t.graph().dummyChains=[],r.forEach(t.edges(),(function(e){!function(t,e){var n,r,a,o=e.v,s=t.node(o).rank,c=e.w,u=t.node(c).rank,l=e.name,h=t.edge(e),f=h.labelRank;if(u!==s+1){for(t.removeEdge(e),a=0,++s;s{var r=n(8436);t.exports=function(t,e,n){var i,a={};r.forEach(n,(function(n){for(var r,o,s=t.parent(n);s;){if((r=t.parent(s))?(o=a[r],a[r]=s):(o=i,i=s),o&&o!==s)return void e.setEdge(o,s);s=r}}))}},5439:(t,e,n)=>{var r=n(8436);t.exports=function(t,e){return r.map(e,(function(e){var n=t.inEdges(e);if(n.length){var i=r.reduce(n,(function(e,n){var r=t.edge(n),i=t.node(n.v);return{sum:e.sum+r.weight*i.order,weight:e.weight+r.weight}}),{sum:0,weight:0});return{v:e,barycenter:i.sum/i.weight,weight:i.weight}}return{v:e}}))}},3128:(t,e,n)=>{var r=n(8436),i=n(574).Graph;t.exports=function(t,e,n){var a=function(t){for(var e;t.hasNode(e=r.uniqueId("_root")););return e}(t),o=new i({compound:!0}).setGraph({root:a}).setDefaultNodeLabel((function(e){return t.node(e)}));return r.forEach(t.nodes(),(function(i){var s=t.node(i),c=t.parent(i);(s.rank===e||s.minRank<=e&&e<=s.maxRank)&&(o.setNode(i),o.setParent(i,c||a),r.forEach(t[n](i),(function(e){var n=e.v===i?e.w:e.v,a=o.edge(n,i),s=r.isUndefined(a)?0:a.weight;o.setEdge(n,i,{weight:t.edge(e).weight+s})})),r.has(s,"minRank")&&o.setNode(i,{borderLeft:s.borderLeft[e],borderRight:s.borderRight[e]}))})),o}},6630:(t,e,n)=>{"use strict";var r=n(8436);function i(t,e,n){for(var i=r.zipObject(n,r.map(n,(function(t,e){return e}))),a=r.flatten(r.map(e,(function(e){return r.sortBy(r.map(t.outEdges(e),(function(e){return{pos:i[e.w],weight:t.edge(e).weight}})),"pos")})),!0),o=1;o0;)e%2&&(n+=c[e+1]),c[e=e-1>>1]+=t.weight;u+=t.weight*n}))),u}t.exports=function(t,e){for(var n=0,r=1;r{"use strict";var r=n(8436),i=n(2588),a=n(6630),o=n(1026),s=n(3128),c=n(5093),u=n(574).Graph,l=n(1138);function h(t,e,n){return r.map(e,(function(e){return s(t,e,n)}))}function f(t,e){var n=new u;r.forEach(t,(function(t){var i=t.graph().root,a=o(t,i,n,e);r.forEach(a.vs,(function(e,n){t.node(e).order=n})),c(t,n,a.vs)}))}function d(t,e){r.forEach(e,(function(e){r.forEach(e,(function(e,n){t.node(e).order=n}))}))}t.exports=function(t){var e=l.maxRank(t),n=h(t,r.range(1,e+1),"inEdges"),o=h(t,r.range(e-1,-1,-1),"outEdges"),s=i(t);d(t,s);for(var c,u=Number.POSITIVE_INFINITY,p=0,y=0;y<4;++p,++y){f(p%2?n:o,p%4>=2),s=l.buildLayerMatrix(t);var g=a(t,s);g{"use strict";var r=n(8436);t.exports=function(t){var e={},n=r.filter(t.nodes(),(function(e){return!t.children(e).length})),i=r.max(r.map(n,(function(e){return t.node(e).rank}))),a=r.map(r.range(i+1),(function(){return[]})),o=r.sortBy(n,(function(e){return t.node(e).rank}));return r.forEach(o,(function n(i){if(!r.has(e,i)){e[i]=!0;var o=t.node(i);a[o.rank].push(i),r.forEach(t.successors(i),n)}})),a}},9567:(t,e,n)=>{"use strict";var r=n(8436);t.exports=function(t,e){var n={};return r.forEach(t,(function(t,e){var i=n[t.v]={indegree:0,in:[],out:[],vs:[t.v],i:e};r.isUndefined(t.barycenter)||(i.barycenter=t.barycenter,i.weight=t.weight)})),r.forEach(e.edges(),(function(t){var e=n[t.v],i=n[t.w];r.isUndefined(e)||r.isUndefined(i)||(i.indegree++,e.out.push(n[t.w]))})),function(t){var e=[];function n(t){return function(e){var n,i,a,o;e.merged||(r.isUndefined(e.barycenter)||r.isUndefined(t.barycenter)||e.barycenter>=t.barycenter)&&(i=e,a=0,o=0,(n=t).weight&&(a+=n.barycenter*n.weight,o+=n.weight),i.weight&&(a+=i.barycenter*i.weight,o+=i.weight),n.vs=i.vs.concat(n.vs),n.barycenter=a/o,n.weight=o,n.i=Math.min(i.i,n.i),i.merged=!0)}}function i(e){return function(n){n.in.push(e),0==--n.indegree&&t.push(n)}}for(;t.length;){var a=t.pop();e.push(a),r.forEach(a.in.reverse(),n(a)),r.forEach(a.out,i(a))}return r.map(r.filter(e,(function(t){return!t.merged})),(function(t){return r.pick(t,["vs","i","barycenter","weight"])}))}(r.filter(n,(function(t){return!t.indegree})))}},1026:(t,e,n)=>{var r=n(8436),i=n(5439),a=n(9567),o=n(7304);t.exports=function t(e,n,s,c){var u=e.children(n),l=e.node(n),h=l?l.borderLeft:void 0,f=l?l.borderRight:void 0,d={};h&&(u=r.filter(u,(function(t){return t!==h&&t!==f})));var p=i(e,u);r.forEach(p,(function(n){if(e.children(n.v).length){var i=t(e,n.v,s,c);d[n.v]=i,r.has(i,"barycenter")&&(a=n,o=i,r.isUndefined(a.barycenter)?(a.barycenter=o.barycenter,a.weight=o.weight):(a.barycenter=(a.barycenter*a.weight+o.barycenter*o.weight)/(a.weight+o.weight),a.weight+=o.weight))}var a,o}));var y=a(p,s);!function(t,e){r.forEach(t,(function(t){t.vs=r.flatten(t.vs.map((function(t){return e[t]?e[t].vs:t})),!0)}))}(y,d);var g=o(y,c);if(h&&(g.vs=r.flatten([h,g.vs,f],!0),e.predecessors(h).length)){var m=e.node(e.predecessors(h)[0]),v=e.node(e.predecessors(f)[0]);r.has(g,"barycenter")||(g.barycenter=0,g.weight=0),g.barycenter=(g.barycenter*g.weight+m.order+v.order)/(g.weight+2),g.weight+=2}return g}},7304:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n){for(var i;e.length&&(i=r.last(e)).i<=n;)e.pop(),t.push(i.vs),n++;return n}t.exports=function(t,e){var n,o=i.partition(t,(function(t){return r.has(t,"barycenter")})),s=o.lhs,c=r.sortBy(o.rhs,(function(t){return-t.i})),u=[],l=0,h=0,f=0;s.sort((n=!!e,function(t,e){return t.barycentere.barycenter?1:n?e.i-t.i:t.i-e.i})),f=a(u,c,f),r.forEach(s,(function(t){f+=t.vs.length,u.push(t.vs),l+=t.barycenter*t.weight,h+=t.weight,f=a(u,c,f)}));var d={vs:r.flatten(u,!0)};return h&&(d.barycenter=l/h,d.weight=h),d}},4219:(t,e,n)=>{var r=n(8436);t.exports=function(t){var e=function(t){var e={},n=0;return r.forEach(t.children(),(function i(a){var o=n;r.forEach(t.children(a),i),e[a]={low:o,lim:n++}})),e}(t);r.forEach(t.graph().dummyChains,(function(n){for(var r=t.node(n),i=r.edgeObj,a=function(t,e,n,r){var i,a,o=[],s=[],c=Math.min(e[n].low,e[r].low),u=Math.max(e[n].lim,e[r].lim);i=n;do{i=t.parent(i),o.push(i)}while(i&&(e[i].low>c||u>e[i].lim));for(a=i,i=r;(i=t.parent(i))!==a;)s.push(i);return{path:o.concat(s.reverse()),lca:a}}(t,e,i.v,i.w),o=a.path,s=a.lca,c=0,u=o[c],l=!0;n!==i.w;){if(r=t.node(n),l){for(;(u=o[c])!==s&&t.node(u).maxRank{"use strict";var r=n(8436),i=n(574).Graph,a=n(1138);function o(t,e){var n={};return r.reduce(e,(function(e,i){var a=0,o=0,s=e.length,u=r.last(i);return r.forEach(i,(function(e,l){var h=function(t,e){if(t.node(e).dummy)return r.find(t.predecessors(e),(function(e){return t.node(e).dummy}))}(t,e),f=h?t.node(h).order:s;(h||e===u)&&(r.forEach(i.slice(o,l+1),(function(e){r.forEach(t.predecessors(e),(function(r){var i=t.node(r),o=i.order;!(os)&&c(n,e,u)}))}))}return r.reduce(e,(function(e,n){var a,o=-1,s=0;return r.forEach(n,(function(r,c){if("border"===t.node(r).dummy){var u=t.predecessors(r);u.length&&(a=t.node(u[0]).order,i(n,s,c,o,a),s=c,o=a)}i(n,s,n.length,a,e.length)})),n})),n}function c(t,e,n){if(e>n){var r=e;e=n,n=r}var i=t[e];i||(t[e]=i={}),i[n]=!0}function u(t,e,n){if(e>n){var i=e;e=n,n=i}return r.has(t[e],n)}function l(t,e,n,i){var a={},o={},s={};return r.forEach(e,(function(t){r.forEach(t,(function(t,e){a[t]=t,o[t]=t,s[t]=e}))})),r.forEach(e,(function(t){var e=-1;r.forEach(t,(function(t){var c=i(t);if(c.length)for(var l=((c=r.sortBy(c,(function(t){return s[t]}))).length-1)/2,h=Math.floor(l),f=Math.ceil(l);h<=f;++h){var d=c[h];o[t]===t&&e{"use strict";var r=n(8436),i=n(1138),a=n(3573).positionX;t.exports=function(t){(function(t){var e=i.buildLayerMatrix(t),n=t.graph().ranksep,a=0;r.forEach(e,(function(e){var i=r.max(r.map(e,(function(e){return t.node(e).height})));r.forEach(e,(function(e){t.node(e).y=a+i/2})),a+=i+n}))})(t=i.asNonCompoundGraph(t)),r.forEach(a(t),(function(e,n){t.node(n).x=e}))}},300:(t,e,n)=>{"use strict";var r=n(8436),i=n(574).Graph,a=n(6681).slack;function o(t,e){return r.forEach(t.nodes(),(function n(i){r.forEach(e.nodeEdges(i),(function(r){var o=r.v,s=i===o?r.w:o;t.hasNode(s)||a(e,r)||(t.setNode(s,{}),t.setEdge(i,s,{}),n(s))}))})),t.nodeCount()}function s(t,e){return r.minBy(e.edges(),(function(n){if(t.hasNode(n.v)!==t.hasNode(n.w))return a(e,n)}))}function c(t,e,n){r.forEach(t.nodes(),(function(t){e.node(t).rank+=n}))}t.exports=function(t){var e,n,r=new i({directed:!1}),u=t.nodes()[0],l=t.nodeCount();for(r.setNode(u,{});o(r,t){"use strict";var r=n(6681).longestPath,i=n(300),a=n(2472);t.exports=function(t){switch(t.graph().ranker){case"network-simplex":default:!function(t){a(t)}(t);break;case"tight-tree":!function(t){r(t),i(t)}(t);break;case"longest-path":o(t)}};var o=r},2472:(t,e,n)=>{"use strict";var r=n(8436),i=n(300),a=n(6681).slack,o=n(6681).longestPath,s=n(574).alg.preorder,c=n(574).alg.postorder,u=n(1138).simplify;function l(t){t=u(t),o(t);var e,n=i(t);for(d(n),h(n,t);e=y(n);)m(n,t,e,g(n,t,e))}function h(t,e){var n=c(t,t.nodes());n=n.slice(0,n.length-1),r.forEach(n,(function(n){!function(t,e,n){var r=t.node(n).parent;t.edge(n,r).cutvalue=f(t,e,n)}(t,e,n)}))}function f(t,e,n){var i=t.node(n).parent,a=!0,o=e.edge(n,i),s=0;return o||(a=!1,o=e.edge(i,n)),s=o.weight,r.forEach(e.nodeEdges(n),(function(r){var o,c,u=r.v===n,l=u?r.w:r.v;if(l!==i){var h=u===a,f=e.edge(r).weight;if(s+=h?f:-f,o=n,c=l,t.hasEdge(o,c)){var d=t.edge(n,l).cutvalue;s+=h?-d:d}}})),s}function d(t,e){arguments.length<2&&(e=t.nodes()[0]),p(t,{},1,e)}function p(t,e,n,i,a){var o=n,s=t.node(i);return e[i]=!0,r.forEach(t.neighbors(i),(function(a){r.has(e,a)||(n=p(t,e,n,a,i))})),s.low=o,s.lim=n++,a?s.parent=a:delete s.parent,n}function y(t){return r.find(t.edges(),(function(e){return t.edge(e).cutvalue<0}))}function g(t,e,n){var i=n.v,o=n.w;e.hasEdge(i,o)||(i=n.w,o=n.v);var s=t.node(i),c=t.node(o),u=s,l=!1;s.lim>c.lim&&(u=c,l=!0);var h=r.filter(e.edges(),(function(e){return l===v(0,t.node(e.v),u)&&l!==v(0,t.node(e.w),u)}));return r.minBy(h,(function(t){return a(e,t)}))}function m(t,e,n,i){var a=n.v,o=n.w;t.removeEdge(a,o),t.setEdge(i.v,i.w,{}),d(t),h(t,e),function(t,e){var n=r.find(t.nodes(),(function(t){return!e.node(t).parent})),i=s(t,n);i=i.slice(1),r.forEach(i,(function(n){var r=t.node(n).parent,i=e.edge(n,r),a=!1;i||(i=e.edge(r,n),a=!0),e.node(n).rank=e.node(r).rank+(a?i.minlen:-i.minlen)}))}(t,e)}function v(t,e,n){return n.low<=e.lim&&e.lim<=n.lim}t.exports=l,l.initLowLimValues=d,l.initCutValues=h,l.calcCutValue=f,l.leaveEdge=y,l.enterEdge=g,l.exchangeEdges=m},6681:(t,e,n)=>{"use strict";var r=n(8436);t.exports={longestPath:function(t){var e={};r.forEach(t.sources(),(function n(i){var a=t.node(i);if(r.has(e,i))return a.rank;e[i]=!0;var o=r.min(r.map(t.outEdges(i),(function(e){return n(e.w)-t.edge(e).minlen})));return o!==Number.POSITIVE_INFINITY&&null!=o||(o=0),a.rank=o}))},slack:function(t,e){return t.node(e.w).rank-t.node(e.v).rank-t.edge(e).minlen}}},1138:(t,e,n)=>{"use strict";var r=n(8436),i=n(574).Graph;function a(t,e,n,i){var a;do{a=r.uniqueId(i)}while(t.hasNode(a));return n.dummy=e,t.setNode(a,n),a}function o(t){return r.max(r.map(t.nodes(),(function(e){var n=t.node(e).rank;if(!r.isUndefined(n))return n})))}t.exports={addDummyNode:a,simplify:function(t){var e=(new i).setGraph(t.graph());return r.forEach(t.nodes(),(function(n){e.setNode(n,t.node(n))})),r.forEach(t.edges(),(function(n){var r=e.edge(n.v,n.w)||{weight:0,minlen:1},i=t.edge(n);e.setEdge(n.v,n.w,{weight:r.weight+i.weight,minlen:Math.max(r.minlen,i.minlen)})})),e},asNonCompoundGraph:function(t){var e=new i({multigraph:t.isMultigraph()}).setGraph(t.graph());return r.forEach(t.nodes(),(function(n){t.children(n).length||e.setNode(n,t.node(n))})),r.forEach(t.edges(),(function(n){e.setEdge(n,t.edge(n))})),e},successorWeights:function(t){var e=r.map(t.nodes(),(function(e){var n={};return r.forEach(t.outEdges(e),(function(e){n[e.w]=(n[e.w]||0)+t.edge(e).weight})),n}));return r.zipObject(t.nodes(),e)},predecessorWeights:function(t){var e=r.map(t.nodes(),(function(e){var n={};return r.forEach(t.inEdges(e),(function(e){n[e.v]=(n[e.v]||0)+t.edge(e).weight})),n}));return r.zipObject(t.nodes(),e)},intersectRect:function(t,e){var n,r,i=t.x,a=t.y,o=e.x-i,s=e.y-a,c=t.width/2,u=t.height/2;if(!o&&!s)throw new Error("Not possible to find intersection inside of the rectangle");return Math.abs(s)*c>Math.abs(o)*u?(s<0&&(u=-u),n=u*o/s,r=u):(o<0&&(c=-c),n=c,r=c*s/o),{x:i+n,y:a+r}},buildLayerMatrix:function(t){var e=r.map(r.range(o(t)+1),(function(){return[]}));return r.forEach(t.nodes(),(function(n){var i=t.node(n),a=i.rank;r.isUndefined(a)||(e[a][i.order]=n)})),e},normalizeRanks:function(t){var e=r.min(r.map(t.nodes(),(function(e){return t.node(e).rank})));r.forEach(t.nodes(),(function(n){var i=t.node(n);r.has(i,"rank")&&(i.rank-=e)}))},removeEmptyRanks:function(t){var e=r.min(r.map(t.nodes(),(function(e){return t.node(e).rank}))),n=[];r.forEach(t.nodes(),(function(r){var i=t.node(r).rank-e;n[i]||(n[i]=[]),n[i].push(r)}));var i=0,a=t.graph().nodeRankFactor;r.forEach(n,(function(e,n){r.isUndefined(e)&&n%a!=0?--i:i&&r.forEach(e,(function(e){t.node(e).rank+=i}))}))},addBorderNode:function(t,e,n,r){var i={width:0,height:0};return arguments.length>=4&&(i.rank=n,i.order=r),a(t,"border",i,e)},maxRank:o,partition:function(t,e){var n={lhs:[],rhs:[]};return r.forEach(t,(function(t){e(t)?n.lhs.push(t):n.rhs.push(t)})),n},time:function(t,e){var n=r.now();try{return e()}finally{console.log(t+" time: "+(r.now()-n)+"ms")}},notime:function(t,e){return e()}}},8177:t=>{t.exports="0.8.5"},7856:function(t){t.exports=function(){"use strict";var t=Object.hasOwnProperty,e=Object.setPrototypeOf,n=Object.isFrozen,r=Object.getPrototypeOf,i=Object.getOwnPropertyDescriptor,a=Object.freeze,o=Object.seal,s=Object.create,c="undefined"!=typeof Reflect&&Reflect,u=c.apply,l=c.construct;u||(u=function(t,e,n){return t.apply(e,n)}),a||(a=function(t){return t}),o||(o=function(t){return t}),l||(l=function(t,e){return new(Function.prototype.bind.apply(t,[null].concat(function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e1?n-1:0),i=1;i/gm),j=o(/^data-[\-\w.\u00B7-\uFFFF]/),Y=o(/^aria-[\-\w]+$/),z=o(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),U=o(/^(?:\w+script|data):/i),q=o(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),H="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};function $(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e0&&void 0!==arguments[0]?arguments[0]:W(),n=function(e){return t(e)};if(n.version="2.3.5",n.removed=[],!e||!e.document||9!==e.document.nodeType)return n.isSupported=!1,n;var r=e.document,i=e.document,o=e.DocumentFragment,s=e.HTMLTemplateElement,c=e.Node,u=e.Element,l=e.NodeFilter,h=e.NamedNodeMap,w=void 0===h?e.NamedNodeMap||e.MozNamedAttrMap:h,G=e.HTMLFormElement,X=e.DOMParser,Z=e.trustedTypes,Q=u.prototype,K=E(Q,"cloneNode"),J=E(Q,"nextSibling"),tt=E(Q,"childNodes"),et=E(Q,"parentNode");if("function"==typeof s){var nt=i.createElement("template");nt.content&&nt.content.ownerDocument&&(i=nt.content.ownerDocument)}var rt=V(Z,r),it=rt?rt.createHTML(""):"",at=i,ot=at.implementation,st=at.createNodeIterator,ct=at.createDocumentFragment,ut=at.getElementsByTagName,lt=r.importNode,ht={};try{ht=T(i).documentMode?i.documentMode:{}}catch(t){}var ft={};n.isSupported="function"==typeof et&&ot&&void 0!==ot.createHTMLDocument&&9!==ht;var dt=F,pt=P,yt=j,gt=Y,mt=U,vt=q,bt=z,_t=null,xt=k({},[].concat($(C),$(S),$(A),$(N),$(O))),wt=null,kt=k({},[].concat($(B),$(L),$(I),$(R))),Tt=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Et=null,Ct=null,St=!0,At=!0,Mt=!1,Nt=!1,Dt=!1,Ot=!1,Bt=!1,Lt=!1,It=!1,Rt=!1,Ft=!0,Pt=!0,jt=!1,Yt={},zt=null,Ut=k({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),qt=null,Ht=k({},["audio","video","img","source","image","track"]),$t=null,Wt=k({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Vt="http://www.w3.org/1998/Math/MathML",Gt="http://www.w3.org/2000/svg",Xt="http://www.w3.org/1999/xhtml",Zt=Xt,Qt=!1,Kt=void 0,Jt=["application/xhtml+xml","text/html"],te="text/html",ee=void 0,ne=null,re=i.createElement("form"),ie=function(t){return t instanceof RegExp||t instanceof Function},ae=function(t){ne&&ne===t||(t&&"object"===(void 0===t?"undefined":H(t))||(t={}),t=T(t),_t="ALLOWED_TAGS"in t?k({},t.ALLOWED_TAGS):xt,wt="ALLOWED_ATTR"in t?k({},t.ALLOWED_ATTR):kt,$t="ADD_URI_SAFE_ATTR"in t?k(T(Wt),t.ADD_URI_SAFE_ATTR):Wt,qt="ADD_DATA_URI_TAGS"in t?k(T(Ht),t.ADD_DATA_URI_TAGS):Ht,zt="FORBID_CONTENTS"in t?k({},t.FORBID_CONTENTS):Ut,Et="FORBID_TAGS"in t?k({},t.FORBID_TAGS):{},Ct="FORBID_ATTR"in t?k({},t.FORBID_ATTR):{},Yt="USE_PROFILES"in t&&t.USE_PROFILES,St=!1!==t.ALLOW_ARIA_ATTR,At=!1!==t.ALLOW_DATA_ATTR,Mt=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Nt=t.SAFE_FOR_TEMPLATES||!1,Dt=t.WHOLE_DOCUMENT||!1,Lt=t.RETURN_DOM||!1,It=t.RETURN_DOM_FRAGMENT||!1,Rt=t.RETURN_TRUSTED_TYPE||!1,Bt=t.FORCE_BODY||!1,Ft=!1!==t.SANITIZE_DOM,Pt=!1!==t.KEEP_CONTENT,jt=t.IN_PLACE||!1,bt=t.ALLOWED_URI_REGEXP||bt,Zt=t.NAMESPACE||Xt,t.CUSTOM_ELEMENT_HANDLING&&ie(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Tt.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&ie(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Tt.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Tt.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Kt=Kt=-1===Jt.indexOf(t.PARSER_MEDIA_TYPE)?te:t.PARSER_MEDIA_TYPE,ee="application/xhtml+xml"===Kt?function(t){return t}:y,Nt&&(At=!1),It&&(Lt=!0),Yt&&(_t=k({},[].concat($(O))),wt=[],!0===Yt.html&&(k(_t,C),k(wt,B)),!0===Yt.svg&&(k(_t,S),k(wt,L),k(wt,R)),!0===Yt.svgFilters&&(k(_t,A),k(wt,L),k(wt,R)),!0===Yt.mathMl&&(k(_t,N),k(wt,I),k(wt,R))),t.ADD_TAGS&&(_t===xt&&(_t=T(_t)),k(_t,t.ADD_TAGS)),t.ADD_ATTR&&(wt===kt&&(wt=T(wt)),k(wt,t.ADD_ATTR)),t.ADD_URI_SAFE_ATTR&&k($t,t.ADD_URI_SAFE_ATTR),t.FORBID_CONTENTS&&(zt===Ut&&(zt=T(zt)),k(zt,t.FORBID_CONTENTS)),Pt&&(_t["#text"]=!0),Dt&&k(_t,["html","head","body"]),_t.table&&(k(_t,["tbody"]),delete Et.tbody),a&&a(t),ne=t)},oe=k({},["mi","mo","mn","ms","mtext"]),se=k({},["foreignobject","desc","title","annotation-xml"]),ce=k({},S);k(ce,A),k(ce,M);var ue=k({},N);k(ue,D);var le=function(t){var e=et(t);e&&e.tagName||(e={namespaceURI:Xt,tagName:"template"});var n=y(t.tagName),r=y(e.tagName);if(t.namespaceURI===Gt)return e.namespaceURI===Xt?"svg"===n:e.namespaceURI===Vt?"svg"===n&&("annotation-xml"===r||oe[r]):Boolean(ce[n]);if(t.namespaceURI===Vt)return e.namespaceURI===Xt?"math"===n:e.namespaceURI===Gt?"math"===n&&se[r]:Boolean(ue[n]);if(t.namespaceURI===Xt){if(e.namespaceURI===Gt&&!se[r])return!1;if(e.namespaceURI===Vt&&!oe[r])return!1;var i=k({},["title","style","font","a","script"]);return!ue[n]&&(i[n]||!ce[n])}return!1},he=function(t){p(n.removed,{element:t});try{t.parentNode.removeChild(t)}catch(e){try{t.outerHTML=it}catch(e){t.remove()}}},fe=function(t,e){try{p(n.removed,{attribute:e.getAttributeNode(t),from:e})}catch(t){p(n.removed,{attribute:null,from:e})}if(e.removeAttribute(t),"is"===t&&!wt[t])if(Lt||It)try{he(e)}catch(t){}else try{e.setAttribute(t,"")}catch(t){}},de=function(t){var e=void 0,n=void 0;if(Bt)t=""+t;else{var r=g(t,/^[\r\n\t ]+/);n=r&&r[0]}"application/xhtml+xml"===Kt&&(t=''+t+"");var a=rt?rt.createHTML(t):t;if(Zt===Xt)try{e=(new X).parseFromString(a,Kt)}catch(t){}if(!e||!e.documentElement){e=ot.createDocument(Zt,"template",null);try{e.documentElement.innerHTML=Qt?"":a}catch(t){}}var o=e.body||e.documentElement;return t&&n&&o.insertBefore(i.createTextNode(n),o.childNodes[0]||null),Zt===Xt?ut.call(e,Dt?"html":"body")[0]:Dt?e.documentElement:o},pe=function(t){return st.call(t.ownerDocument||t,t,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT,null,!1)},ye=function(t){return t instanceof G&&("string"!=typeof t.nodeName||"string"!=typeof t.textContent||"function"!=typeof t.removeChild||!(t.attributes instanceof w)||"function"!=typeof t.removeAttribute||"function"!=typeof t.setAttribute||"string"!=typeof t.namespaceURI||"function"!=typeof t.insertBefore)},ge=function(t){return"object"===(void 0===c?"undefined":H(c))?t instanceof c:t&&"object"===(void 0===t?"undefined":H(t))&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName},me=function(t,e,r){ft[t]&&f(ft[t],(function(t){t.call(n,e,r,ne)}))},ve=function(t){var e=void 0;if(me("beforeSanitizeElements",t,null),ye(t))return he(t),!0;if(g(t.nodeName,/[\u0080-\uFFFF]/))return he(t),!0;var r=ee(t.nodeName);if(me("uponSanitizeElement",t,{tagName:r,allowedTags:_t}),!ge(t.firstElementChild)&&(!ge(t.content)||!ge(t.content.firstElementChild))&&_(/<[/\w]/g,t.innerHTML)&&_(/<[/\w]/g,t.textContent))return he(t),!0;if("select"===r&&_(/