From 389b63f2f7a40f376b9c1fda92e110fc59ff9bd4 Mon Sep 17 00:00:00 2001 From: mario4tier <4542410+mario4tier@users.noreply.github.com> Date: Wed, 14 Feb 2024 03:11:53 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20ChainMov?= =?UTF-8?q?ers/dtp@06cbe609523dc1510749957198ccf7ab64f665aa=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 41 +- assets/404.html-B7K0IBbl.js | 1 + assets/api_rust.html-BxLNqA0i.js | 1 + assets/api_rust.html-jEWBwXo5.js | 1 + assets/api_typescript.html-C6Hyg1mu.js | 1 + assets/api_typescript.html-DpDyABcd.js | 1 + assets/app-DlOHg9Xr.js | 30 + assets/design.html-BCNdCdft.js | 1 + assets/design.html-BzmiLaM4.js | 1 + assets/editors.html-DwjnlUpI.js | 7 + assets/faq.html-B9wOlu7B.js | 1 + assets/{images => }/favicon.png | Bin assets/full_setup.html-CCMysVzO.js | 38 + assets/future_work.html-BqJ-TElc.js | 1 + assets/future_work.html-iK8jJpLI.js | 1 + assets/icon/apple-icon-152.png | Bin 0 -> 3568 bytes assets/icon/chrome-192.png | Bin 0 -> 4733 bytes assets/icon/chrome-512.png | Bin 0 -> 13251 bytes assets/icon/chrome-mask-192.png | Bin 0 -> 4755 bytes assets/icon/chrome-mask-512.png | Bin 0 -> 13040 bytes assets/icon/guide-maskable.png | Bin 0 -> 2270 bytes assets/icon/ms-icon-144.png | Bin 0 -> 3657 bytes assets/image/advanced.svg | 1 + assets/image/blog.svg | 1 + assets/image/box.svg | 1 + assets/image/features.svg | 1 + assets/image/github-dark.svg | 1 + assets/image/github-light.svg | 1 + assets/image/layout.svg | 1 + assets/image/markdown.svg | 1 + assets/images/HomeStackArrowCapy.png | Bin assets/images/design_terms.png | Bin assets/images/example_rpc_firewall.png | Bin assets/images/example_web3.png | Bin assets/images/free_icon.svg | 1 + assets/images/home_high_level.png | Bin assets/images/home_top_capy.png | Bin assets/images/multi_channels.png | Bin assets/images/p2p_broadcast.png | Bin assets/images/propose-change.png | Bin 0 -> 10764 bytes assets/images/ref_broadcast.png | Bin assets/images/ref_firewall.png | Bin assets/images/ref_ha.png | Bin assets/images/ref_uni.png | Bin assets/images/setup_help_services.png | Bin assets/images/total_vs_partial_order.PNG | Bin .../images/total_vs_partial_order_small.PNG | Bin assets/index.html-2JbiJiHq.js | 1 + assets/index.html-BSnE9a5s.js | 1 + assets/index.html-BbkzL85r.js | 1 + assets/index.html-By-UCih8.js | 1 + assets/index.html-K9gGP3vT.js | 1 + assets/index.html-xbvo-U6r.js | 1 + assets/install.html-BizGowkj.js | 1 + assets/intro.html-DJw2Nump.js | 1 + assets/javascripts/bundle.b7178837.min.js | 3 - assets/javascripts/lunr/min/lunr.ar.min.js | 1 - assets/javascripts/lunr/min/lunr.da.min.js | 18 - assets/javascripts/lunr/min/lunr.de.min.js | 18 - assets/javascripts/lunr/min/lunr.du.min.js | 18 - assets/javascripts/lunr/min/lunr.es.min.js | 18 - assets/javascripts/lunr/min/lunr.fi.min.js | 18 - assets/javascripts/lunr/min/lunr.fr.min.js | 18 - assets/javascripts/lunr/min/lunr.hi.min.js | 1 - assets/javascripts/lunr/min/lunr.hu.min.js | 18 - assets/javascripts/lunr/min/lunr.it.min.js | 18 - assets/javascripts/lunr/min/lunr.ja.min.js | 1 - assets/javascripts/lunr/min/lunr.jp.min.js | 1 - assets/javascripts/lunr/min/lunr.ko.min.js | 1 - assets/javascripts/lunr/min/lunr.multi.min.js | 1 - assets/javascripts/lunr/min/lunr.nl.min.js | 18 - assets/javascripts/lunr/min/lunr.no.min.js | 18 - assets/javascripts/lunr/min/lunr.pt.min.js | 18 - assets/javascripts/lunr/min/lunr.ro.min.js | 18 - assets/javascripts/lunr/min/lunr.ru.min.js | 18 - .../lunr/min/lunr.stemmer.support.min.js | 1 - assets/javascripts/lunr/min/lunr.sv.min.js | 18 - assets/javascripts/lunr/min/lunr.ta.min.js | 1 - assets/javascripts/lunr/min/lunr.th.min.js | 1 - assets/javascripts/lunr/min/lunr.tr.min.js | 18 - assets/javascripts/lunr/min/lunr.vi.min.js | 1 - assets/javascripts/lunr/min/lunr.zh.min.js | 1 - assets/javascripts/lunr/tinyseg.js | 206 - assets/javascripts/lunr/wordcut.js | 6708 ----------------- .../workers/search.6c7302c4.min.js | 2 - assets/npm_only.html-Bs9x0lRw.js | 1 + assets/p2p_broadcast-DKREXEsi.js | 1 + assets/photoswipe.esm-SzV8tJDW.js | 4 + assets/plugin-vue_export-helper-DlAUqK2U.js | 1 + assets/ref_broadcast-Cg4jrlCe.js | 1 + assets/rpc_firewall.html-C8sUbYFf.js | 1 + assets/runtime_only.html-BsGx0Xbr.js | 1 + assets/scripts.html-Cae6ml7k.js | 1 + assets/scripts.html-D_w4s9EQ.js | 1 + assets/style-Ceu9ObI8.css | 1 + assets/stylesheets/main.e95b5de1.min.css | 1 - assets/stylesheets/palette.6932e648.min.css | 1 - assets/web3_rust.html-D5SN0Dc_.js | 1 + community/editors.html | 46 + community/index.html | 41 +- docs/api_rust.html | 40 + docs/api_typescript.html | 40 + docs/design.html | 40 + docs/future_work.html | 40 + docs/index.html | 40 + docs/scripts.html | 40 + example/rpc_firewall/index.html | 1 - example/web3_rust/index.html | 1 - examples/index.html | 41 +- examples/rpc_firewall.html | 40 + examples/web3_rust.html | 40 + faq.html | 40 + faq/index.html | 1 - favicon.ico | Bin 0 -> 67646 bytes how-to/full_setup.html | 77 + how-to/index.html | 40 + how-to/install.html | 40 + how-to/npm_only.html | 40 + how-to/runtime_only.html | 40 + index.html | 44 +- intro.html | 40 + assets/logo.png => logo.png | Bin logo.svg | 1 + overrides/partials/disable_copyright.html | 0 ref/api/index.html | 1 - ref/api_rust.html | 40 + ref/api_rust/index.html | 1 - ref/api_typescript.html | 40 + ref/api_typescript/index.html | 1 - ref/design.html | 40 + ref/design/index.html | 1 - ref/future_work.html | 40 + ref/future_work/index.html | 1 - ref/index.html | 40 + ref/readme/index.html | 1 - ref/scripts.html | 40 + ref/scripts/index.html | 1 - robots.txt | 5 + search/search_index.json | 1 - setup/help/index.html | 1 - setup/rust/index.html | 38 - setup/services/index.html | 1 - sitemap.xml | 84 +- sitemap.xml.gz | Bin 206 -> 0 bytes sitemap.xsl | 207 + 145 files changed, 1417 insertions(+), 7339 deletions(-) create mode 100644 assets/404.html-B7K0IBbl.js create mode 100644 assets/api_rust.html-BxLNqA0i.js create mode 100644 assets/api_rust.html-jEWBwXo5.js create mode 100644 assets/api_typescript.html-C6Hyg1mu.js create mode 100644 assets/api_typescript.html-DpDyABcd.js create mode 100644 assets/app-DlOHg9Xr.js create mode 100644 assets/design.html-BCNdCdft.js create mode 100644 assets/design.html-BzmiLaM4.js create mode 100644 assets/editors.html-DwjnlUpI.js create mode 100644 assets/faq.html-B9wOlu7B.js rename assets/{images => }/favicon.png (100%) mode change 100644 => 100755 create mode 100644 assets/full_setup.html-CCMysVzO.js create mode 100644 assets/future_work.html-BqJ-TElc.js create mode 100644 assets/future_work.html-iK8jJpLI.js create mode 100644 assets/icon/apple-icon-152.png create mode 100644 assets/icon/chrome-192.png create mode 100644 assets/icon/chrome-512.png create mode 100644 assets/icon/chrome-mask-192.png create mode 100644 assets/icon/chrome-mask-512.png create mode 100644 assets/icon/guide-maskable.png create mode 100644 assets/icon/ms-icon-144.png create mode 100644 assets/image/advanced.svg create mode 100644 assets/image/blog.svg create mode 100644 assets/image/box.svg create mode 100644 assets/image/features.svg create mode 100644 assets/image/github-dark.svg create mode 100644 assets/image/github-light.svg create mode 100644 assets/image/layout.svg create mode 100644 assets/image/markdown.svg mode change 100644 => 100755 assets/images/HomeStackArrowCapy.png mode change 100644 => 100755 assets/images/design_terms.png mode change 100644 => 100755 assets/images/example_rpc_firewall.png mode change 100644 => 100755 assets/images/example_web3.png create mode 100644 assets/images/free_icon.svg mode change 100644 => 100755 assets/images/home_high_level.png mode change 100644 => 100755 assets/images/home_top_capy.png mode change 100644 => 100755 assets/images/multi_channels.png mode change 100644 => 100755 assets/images/p2p_broadcast.png create mode 100755 assets/images/propose-change.png mode change 100644 => 100755 assets/images/ref_broadcast.png mode change 100644 => 100755 assets/images/ref_firewall.png mode change 100644 => 100755 assets/images/ref_ha.png mode change 100644 => 100755 assets/images/ref_uni.png mode change 100644 => 100755 assets/images/setup_help_services.png mode change 100644 => 100755 assets/images/total_vs_partial_order.PNG mode change 100644 => 100755 assets/images/total_vs_partial_order_small.PNG create mode 100644 assets/index.html-2JbiJiHq.js create mode 100644 assets/index.html-BSnE9a5s.js create mode 100644 assets/index.html-BbkzL85r.js create mode 100644 assets/index.html-By-UCih8.js create mode 100644 assets/index.html-K9gGP3vT.js create mode 100644 assets/index.html-xbvo-U6r.js create mode 100644 assets/install.html-BizGowkj.js create mode 100644 assets/intro.html-DJw2Nump.js delete mode 100644 assets/javascripts/bundle.b7178837.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.da.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.de.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.du.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.es.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.it.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.no.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.th.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js delete mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js delete mode 100644 assets/javascripts/lunr/tinyseg.js delete mode 100644 assets/javascripts/lunr/wordcut.js delete mode 100644 assets/javascripts/workers/search.6c7302c4.min.js create mode 100644 assets/npm_only.html-Bs9x0lRw.js create mode 100644 assets/p2p_broadcast-DKREXEsi.js create mode 100644 assets/photoswipe.esm-SzV8tJDW.js create mode 100644 assets/plugin-vue_export-helper-DlAUqK2U.js create mode 100644 assets/ref_broadcast-Cg4jrlCe.js create mode 100644 assets/rpc_firewall.html-C8sUbYFf.js create mode 100644 assets/runtime_only.html-BsGx0Xbr.js create mode 100644 assets/scripts.html-Cae6ml7k.js create mode 100644 assets/scripts.html-D_w4s9EQ.js create mode 100644 assets/style-Ceu9ObI8.css delete mode 100644 assets/stylesheets/main.e95b5de1.min.css delete mode 100644 assets/stylesheets/palette.6932e648.min.css create mode 100644 assets/web3_rust.html-D5SN0Dc_.js create mode 100644 community/editors.html create mode 100644 docs/api_rust.html create mode 100644 docs/api_typescript.html create mode 100644 docs/design.html create mode 100644 docs/future_work.html create mode 100644 docs/index.html create mode 100644 docs/scripts.html delete mode 100644 example/rpc_firewall/index.html delete mode 100644 example/web3_rust/index.html create mode 100644 examples/rpc_firewall.html create mode 100644 examples/web3_rust.html create mode 100644 faq.html delete mode 100644 faq/index.html create mode 100644 favicon.ico create mode 100644 how-to/full_setup.html create mode 100644 how-to/index.html create mode 100644 how-to/install.html create mode 100644 how-to/npm_only.html create mode 100644 how-to/runtime_only.html create mode 100644 intro.html rename assets/logo.png => logo.png (100%) mode change 100644 => 100755 create mode 100644 logo.svg delete mode 100644 overrides/partials/disable_copyright.html delete mode 100644 ref/api/index.html create mode 100644 ref/api_rust.html delete mode 100644 ref/api_rust/index.html create mode 100644 ref/api_typescript.html delete mode 100644 ref/api_typescript/index.html create mode 100644 ref/design.html delete mode 100644 ref/design/index.html create mode 100644 ref/future_work.html delete mode 100644 ref/future_work/index.html create mode 100644 ref/index.html delete mode 100644 ref/readme/index.html create mode 100644 ref/scripts.html delete mode 100644 ref/scripts/index.html create mode 100644 robots.txt delete mode 100644 search/search_index.json delete mode 100644 setup/help/index.html delete mode 100644 setup/rust/index.html delete mode 100644 setup/services/index.html delete mode 100644 sitemap.xml.gz create mode 100644 sitemap.xsl diff --git a/404.html b/404.html index 63b456d..4882e9f 100644 --- a/404.html +++ b/404.html @@ -1 +1,40 @@ - DTP - Decentralized Transport Protocol

404 - Not found

\ No newline at end of file + + + + + + + + + + Decentralized Transport Protocol + + + + + +
Skip to main content

404

Page not found

That’s a Four-Oh-Four.

+ + + diff --git a/assets/404.html-B7K0IBbl.js b/assets/404.html-B7K0IBbl.js new file mode 100644 index 0000000..fbed991 --- /dev/null +++ b/assets/404.html-B7K0IBbl.js @@ -0,0 +1 @@ +import{_ as t}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as e,c as o,a as n}from"./app-DlOHg9Xr.js";const r={},a=n("p",null,"404 Not Found",-1),c=[a];function p(s,i){return e(),o("div",null,c)}const m=t(r,[["render",p],["__file","404.html.vue"]]),_=JSON.parse('{"path":"/404.html","title":"","lang":"en-US","frontmatter":{"layout":"NotFound","description":"404 Not Found ","head":[["meta",{"property":"og:url","content":"https://dtp.dev/404.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":"404 Not Found "}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"\\",\\"description\\":\\"404 Not Found \\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0.01,"words":3},"filePathRelative":null,"autoDesc":true}');export{m as comp,_ as data}; diff --git a/assets/api_rust.html-BxLNqA0i.js b/assets/api_rust.html-BxLNqA0i.js new file mode 100644 index 0000000..97c13e9 --- /dev/null +++ b/assets/api_rust.html-BxLNqA0i.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as r,c as o,a as t}from"./app-DlOHg9Xr.js";const n={},a=t("div",{class:"hint-container warning"},[t("p",{class:"hint-container-title"},"Not yet written")],-1),i=[a];function p(c,s){return r(),o("div",null,i)}const m=e(n,[["render",p],["__file","api_rust.html.vue"]]),u=JSON.parse('{"path":"/ref/api_rust.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":" Not yet written ","head":[["meta",{"property":"og:url","content":"https://dtp.dev/ref/api_rust.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":" Not yet written "}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":null,\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":null,"updatedTime":null,"contributors":[]},"readingTime":{"minutes":0.02,"words":6},"filePathRelative":"ref/api_rust.md","autoDesc":true}');export{m as comp,u as data}; diff --git a/assets/api_rust.html-jEWBwXo5.js b/assets/api_rust.html-jEWBwXo5.js new file mode 100644 index 0000000..1f98dc0 --- /dev/null +++ b/assets/api_rust.html-jEWBwXo5.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o,c as r,a as t}from"./app-DlOHg9Xr.js";const a={},i=t("div",{class:"hint-container warning"},[t("p",{class:"hint-container-title"},"Not yet written")],-1),n=[i];function c(p,s){return o(),r("div",null,n)}const l=e(a,[["render",c],["__file","api_rust.html.vue"]]),_=JSON.parse('{"path":"/docs/api_rust.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":" Not yet written ","head":[["meta",{"property":"og:url","content":"https://dtp.dev/docs/api_rust.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":" Not yet written "}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.02,"words":6},"filePathRelative":"docs/api_rust.md","localizedDate":"February 14, 2024","autoDesc":true}');export{l as comp,_ as data}; diff --git a/assets/api_typescript.html-C6Hyg1mu.js b/assets/api_typescript.html-C6Hyg1mu.js new file mode 100644 index 0000000..95c9eb9 --- /dev/null +++ b/assets/api_typescript.html-C6Hyg1mu.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o,c as r,a as t}from"./app-DlOHg9Xr.js";const i={},a=t("div",{class:"hint-container warning"},[t("p",{class:"hint-container-title"},"Not yet written")],-1),n=[a];function p(c,s){return o(),r("div",null,n)}const l=e(i,[["render",p],["__file","api_typescript.html.vue"]]),_=JSON.parse('{"path":"/docs/api_typescript.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":" Not yet written ","head":[["meta",{"property":"og:url","content":"https://dtp.dev/docs/api_typescript.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":" Not yet written "}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.02,"words":6},"filePathRelative":"docs/api_typescript.md","localizedDate":"February 14, 2024","autoDesc":true}');export{l as comp,_ as data}; diff --git a/assets/api_typescript.html-DpDyABcd.js b/assets/api_typescript.html-DpDyABcd.js new file mode 100644 index 0000000..dd2ec6e --- /dev/null +++ b/assets/api_typescript.html-DpDyABcd.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as r,c as o,a as t}from"./app-DlOHg9Xr.js";const n={},a=t("div",{class:"hint-container warning"},[t("p",{class:"hint-container-title"},"Not yet written")],-1),i=[a];function p(c,s){return r(),o("div",null,i)}const m=e(n,[["render",p],["__file","api_typescript.html.vue"]]),_=JSON.parse('{"path":"/ref/api_typescript.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":" Not yet written ","head":[["meta",{"property":"og:url","content":"https://dtp.dev/ref/api_typescript.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":" Not yet written "}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":null,\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":null,"updatedTime":null,"contributors":[]},"readingTime":{"minutes":0.02,"words":6},"filePathRelative":"ref/api_typescript.md","autoDesc":true}');export{m as comp,_ as data}; diff --git a/assets/app-DlOHg9Xr.js b/assets/app-DlOHg9Xr.js new file mode 100644 index 0000000..c03f3df --- /dev/null +++ b/assets/app-DlOHg9Xr.js @@ -0,0 +1,30 @@ +/** +* @vue/shared v3.4.19 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function qo(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const ve={},sn=[],Je=()=>{},Rc=()=>!1,Xn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Go=e=>e.startsWith("onUpdate:"),we=Object.assign,Ko=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Ic=Object.prototype.hasOwnProperty,le=(e,t)=>Ic.call(e,t),X=Array.isArray,On=e=>Hr(e)==="[object Map]",Pc=e=>Hr(e)==="[object Set]",ee=e=>typeof e=="function",Ae=e=>typeof e=="string",Fr=e=>typeof e=="symbol",me=e=>e!==null&&typeof e=="object",Jl=e=>(me(e)||ee(e))&&ee(e.then)&&ee(e.catch),Oc=Object.prototype.toString,Hr=e=>Oc.call(e),Mc=e=>Hr(e).slice(8,-1),$c=e=>Hr(e)==="[object Object]",Yo=e=>Ae(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,ln=qo(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Br=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Nc=/-(\w)/g,ze=Br(e=>e.replace(Nc,(t,n)=>n?n.toUpperCase():"")),Dc=/\B([A-Z])/g,_n=Br(e=>e.replace(Dc,"-$1").toLowerCase()),wn=Br(e=>e.charAt(0).toUpperCase()+e.slice(1)),to=Br(e=>e?`on${wn(e)}`:""),Ot=(e,t)=>!Object.is(e,t),no=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},Fc=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Hc=e=>{const t=Ae(e)?Number(e):NaN;return isNaN(t)?e:t};let Is;const Ql=()=>Is||(Is=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Jo(e){if(X(e)){const t={};for(let n=0;n{if(n){const r=n.split(jc);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Qo(e){let t="";if(Ae(e))t=e;else if(X(e))for(let n=0;n=4))break}this._dirtyLevel===1&&(this._dirtyLevel=0),Jt()}return this._dirtyLevel>=4}set dirty(t){this._dirtyLevel=t?4:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=It,n=Ut;try{return It=!0,Ut=this,this._runnings++,Ps(this),this.fn()}finally{Os(this),this._runnings--,Ut=n,It=t}}stop(){var t;this.active&&(Ps(this),Os(this),(t=this.onStop)==null||t.call(this),this.active=!1)}}function Yc(e){return e.value}function Ps(e){e._trackId++,e._depsLength=0}function Os(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t{const n=new Map;return n.cleanup=e,n.computed=t,n},Lr=new WeakMap,qt=Symbol(""),ko=Symbol("");function We(e,t,n){if(It&&Ut){let r=Lr.get(e);r||Lr.set(e,r=new Map);let o=r.get(n);o||r.set(n,o=oa(()=>r.delete(n))),na(Ut,o)}}function bt(e,t,n,r,o,s){const l=Lr.get(e);if(!l)return;let a=[];if(t==="clear")a=[...l.values()];else if(n==="length"&&X(e)){const c=Number(r);l.forEach((i,u)=>{(u==="length"||!Fr(u)&&u>=c)&&a.push(i)})}else switch(n!==void 0&&a.push(l.get(n)),t){case"add":X(e)?Yo(n)&&a.push(l.get("length")):(a.push(l.get(qt)),On(e)&&a.push(l.get(ko)));break;case"delete":X(e)||(a.push(l.get(qt)),On(e)&&a.push(l.get(ko)));break;case"set":On(e)&&a.push(l.get(qt));break}Zo();for(const c of a)c&&ra(c,4);es()}function Jc(e,t){var n;return(n=Lr.get(e))==null?void 0:n.get(t)}const Qc=qo("__proto__,__v_isRef,__isVue"),sa=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Fr)),Ms=Xc();function Xc(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=oe(this);for(let s=0,l=this.length;s{e[t]=function(...n){Yt(),Zo();const r=oe(this)[t].apply(this,n);return es(),Jt(),r}}),e}function Zc(e){const t=oe(this);return We(t,"has",e),t.hasOwnProperty(e)}class la{constructor(t=!1,n=!1){this._isReadonly=t,this._shallow=n}get(t,n,r){const o=this._isReadonly,s=this._shallow;if(n==="__v_isReactive")return!o;if(n==="__v_isReadonly")return o;if(n==="__v_isShallow")return s;if(n==="__v_raw")return r===(o?s?du:ua:s?ca:ia).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const l=X(t);if(!o){if(l&&le(Ms,n))return Reflect.get(Ms,n,r);if(n==="hasOwnProperty")return Zc}const a=Reflect.get(t,n,r);return(Fr(n)?sa.has(n):Qc(n))||(o||We(t,"get",n),s)?a:Ie(a)?l&&Yo(n)?a:a.value:me(a)?o?er(a):Zn(a):a}}class aa extends la{constructor(t=!1){super(!1,t)}set(t,n,r,o){let s=t[n];if(!this._shallow){const c=pn(s);if(!Rr(r)&&!pn(r)&&(s=oe(s),r=oe(r)),!X(t)&&Ie(s)&&!Ie(r))return c?!1:(s.value=r,!0)}const l=X(t)&&Yo(n)?Number(n)e,jr=e=>Reflect.getPrototypeOf(e);function dr(e,t,n=!1,r=!1){e=e.__v_raw;const o=oe(e),s=oe(t);n||(Ot(t,s)&&We(o,"get",t),We(o,"get",s));const{has:l}=jr(o),a=r?ts:n?os:Vn;if(l.call(o,t))return a(e.get(t));if(l.call(o,s))return a(e.get(s));e!==o&&e.get(t)}function pr(e,t=!1){const n=this.__v_raw,r=oe(n),o=oe(e);return t||(Ot(e,o)&&We(r,"has",e),We(r,"has",o)),e===o?n.has(e):n.has(e)||n.has(o)}function hr(e,t=!1){return e=e.__v_raw,!t&&We(oe(e),"iterate",qt),Reflect.get(e,"size",e)}function $s(e){e=oe(e);const t=oe(this);return jr(t).has.call(t,e)||(t.add(e),bt(t,"add",e,e)),this}function Ns(e,t){t=oe(t);const n=oe(this),{has:r,get:o}=jr(n);let s=r.call(n,e);s||(e=oe(e),s=r.call(n,e));const l=o.call(n,e);return n.set(e,t),s?Ot(t,l)&&bt(n,"set",e,t):bt(n,"add",e,t),this}function Ds(e){const t=oe(this),{has:n,get:r}=jr(t);let o=n.call(t,e);o||(e=oe(e),o=n.call(t,e)),r&&r.call(t,e);const s=t.delete(e);return o&&bt(t,"delete",e,void 0),s}function Fs(){const e=oe(this),t=e.size!==0,n=e.clear();return t&&bt(e,"clear",void 0,void 0),n}function vr(e,t){return function(r,o){const s=this,l=s.__v_raw,a=oe(l),c=t?ts:e?os:Vn;return!e&&We(a,"iterate",qt),l.forEach((i,u)=>r.call(o,c(i),c(u),s))}}function mr(e,t,n){return function(...r){const o=this.__v_raw,s=oe(o),l=On(s),a=e==="entries"||e===Symbol.iterator&&l,c=e==="keys"&&l,i=o[e](...r),u=n?ts:t?os:Vn;return!t&&We(s,"iterate",c?ko:qt),{next(){const{value:d,done:p}=i.next();return p?{value:d,done:p}:{value:a?[u(d[0]),u(d[1])]:u(d),done:p}},[Symbol.iterator](){return this}}}}function Et(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ou(){const e={get(s){return dr(this,s)},get size(){return hr(this)},has:pr,add:$s,set:Ns,delete:Ds,clear:Fs,forEach:vr(!1,!1)},t={get(s){return dr(this,s,!1,!0)},get size(){return hr(this)},has:pr,add:$s,set:Ns,delete:Ds,clear:Fs,forEach:vr(!1,!0)},n={get(s){return dr(this,s,!0)},get size(){return hr(this,!0)},has(s){return pr.call(this,s,!0)},add:Et("add"),set:Et("set"),delete:Et("delete"),clear:Et("clear"),forEach:vr(!0,!1)},r={get(s){return dr(this,s,!0,!0)},get size(){return hr(this,!0)},has(s){return pr.call(this,s,!0)},add:Et("add"),set:Et("set"),delete:Et("delete"),clear:Et("clear"),forEach:vr(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(s=>{e[s]=mr(s,!1,!1),n[s]=mr(s,!0,!1),t[s]=mr(s,!1,!0),r[s]=mr(s,!0,!0)}),[e,n,t,r]}const[su,lu,au,iu]=ou();function ns(e,t){const n=t?e?iu:au:e?lu:su;return(r,o,s)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?r:Reflect.get(le(n,o)&&o in r?n:r,o,s)}const cu={get:ns(!1,!1)},uu={get:ns(!1,!0)},fu={get:ns(!0,!1)},ia=new WeakMap,ca=new WeakMap,ua=new WeakMap,du=new WeakMap;function pu(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function hu(e){return e.__v_skip||!Object.isExtensible(e)?0:pu(Mc(e))}function Zn(e){return pn(e)?e:rs(e,!1,tu,cu,ia)}function fa(e){return rs(e,!1,ru,uu,ca)}function er(e){return rs(e,!0,nu,fu,ua)}function rs(e,t,n,r,o){if(!me(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const s=o.get(e);if(s)return s;const l=hu(e);if(l===0)return e;const a=new Proxy(e,l===2?r:n);return o.set(e,a),a}function an(e){return pn(e)?an(e.__v_raw):!!(e&&e.__v_isReactive)}function pn(e){return!!(e&&e.__v_isReadonly)}function Rr(e){return!!(e&&e.__v_isShallow)}function da(e){return an(e)||pn(e)}function oe(e){const t=e&&e.__v_raw;return t?oe(t):e}function pa(e){return Object.isExtensible(e)&&Ar(e,"__v_skip",!0),e}const Vn=e=>me(e)?Zn(e):e,os=e=>me(e)?er(e):e;class ha{constructor(t,n,r,o){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new Xo(()=>t(this._value),()=>Mn(this,this.effect._dirtyLevel===2?2:3)),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=r}get value(){const t=oe(this);return(!t._cacheable||t.effect.dirty)&&Ot(t._value,t._value=t.effect.run())&&Mn(t,4),ss(t),t.effect._dirtyLevel>=2&&Mn(t,2),t._value}set value(t){this._setter(t)}get _dirty(){return this.effect.dirty}set _dirty(t){this.effect.dirty=t}}function vu(e,t,n=!1){let r,o;const s=ee(e);return s?(r=e,o=Je):(r=e.get,o=e.set),new ha(r,o,s||!o,n)}function ss(e){var t;It&&Ut&&(e=oe(e),na(Ut,(t=e.dep)!=null?t:e.dep=oa(()=>e.dep=void 0,e instanceof ha?e:void 0)))}function Mn(e,t=4,n){e=oe(e);const r=e.dep;r&&ra(r,t)}function Ie(e){return!!(e&&e.__v_isRef===!0)}function te(e){return va(e,!1)}function Fe(e){return va(e,!0)}function va(e,t){return Ie(e)?e:new mu(e,t)}class mu{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:oe(t),this._value=n?t:Vn(t)}get value(){return ss(this),this._value}set value(t){const n=this.__v_isShallow||Rr(t)||pn(t);t=n?t:oe(t),Ot(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Vn(t),Mn(this,4))}}function Gt(e){return Ie(e)?e.value:e}const gu={get:(e,t,n)=>Gt(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return Ie(o)&&!Ie(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function ma(e){return an(e)?e:new Proxy(e,gu)}class bu{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>ss(this),()=>Mn(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function ga(e){return new bu(e)}class yu{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Jc(oe(this._object),this._key)}}class _u{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function Vr(e,t,n){return Ie(e)?e:ee(e)?new _u(e):me(e)&&arguments.length>1?wu(e,t,n):te(e)}function wu(e,t,n){const r=e[t];return Ie(r)?r:new yu(e,t,n)}/** +* @vue/runtime-core v3.4.19 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Pt(e,t,n,r){try{return r?e(...r):e()}catch(o){tr(o,t,n)}}function Xe(e,t,n,r){if(ee(e)){const s=Pt(e,t,n,r);return s&&Jl(s)&&s.catch(l=>{tr(l,t,n)}),s}const o=[];for(let s=0;s>>1,o=Me[r],s=Wn(o);sut&&Me.splice(t,1)}function Su(e){X(e)?cn.push(...e):(!Tt||!Tt.includes(e,e.allowRecurse?Vt+1:Vt))&&cn.push(e),ya()}function Hs(e,t,n=zn?ut+1:0){for(;nWn(n)-Wn(r));if(cn.length=0,Tt){Tt.push(...t);return}for(Tt=t,Vt=0;Vte.id==null?1/0:e.id,Tu=(e,t)=>{const n=Wn(e)-Wn(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function _a(e){Ao=!1,zn=!0,Me.sort(Tu);try{for(ut=0;utAe(m)?m.trim():m)),d&&(o=n.map(Fc))}let a,c=r[a=to(t)]||r[a=to(ze(t))];!c&&s&&(c=r[a=to(_n(t))]),c&&Xe(c,e,6,o);const i=r[a+"Once"];if(i){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,Xe(i,e,6,o)}}function wa(e,t,n=!1){const r=t.emitsCache,o=r.get(e);if(o!==void 0)return o;const s=e.emits;let l={},a=!1;if(!ee(e)){const c=i=>{const u=wa(i,t,!0);u&&(a=!0,we(l,u))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!s&&!a?(me(e)&&r.set(e,null),null):(X(s)?s.forEach(c=>l[c]=null):we(l,s),me(e)&&r.set(e,l),l)}function Wr(e,t){return!e||!Xn(t)?!1:(t=t.slice(2).replace(/Once$/,""),le(e,t[0].toLowerCase()+t.slice(1))||le(e,_n(t))||le(e,t))}let Qe=null,Ea=null;function Pr(e){const t=Qe;return Qe=e,Ea=e&&e.type.__scopeId||null,t}function Au(e,t=Qe,n){if(!t||e._n)return e;const r=(...o)=>{r._d&&Qs(-1);const s=Pr(t);let l;try{l=e(...o)}finally{Pr(s),r._d&&Qs(1)}return l};return r._n=!0,r._c=!0,r._d=!0,r}function ro(e){const{type:t,vnode:n,proxy:r,withProxy:o,props:s,propsOptions:[l],slots:a,attrs:c,emit:i,render:u,renderCache:d,data:p,setupState:m,ctx:g,inheritAttrs:E}=e;let w,b;const S=Pr(e);try{if(n.shapeFlag&4){const x=o||r,$=x;w=tt(u.call($,x,d,s,m,p,g)),b=c}else{const x=t;w=tt(x.length>1?x(s,{attrs:c,slots:a,emit:i}):x(s,null)),b=t.props?c:Lu(c)}}catch(x){Hn.length=0,tr(x,e,1),w=Ce(ft)}let y=w;if(b&&E!==!1){const x=Object.keys(b),{shapeFlag:$}=y;x.length&&$&7&&(l&&x.some(Go)&&(b=Ru(b,l)),y=Mt(y,b))}return n.dirs&&(y=Mt(y),y.dirs=y.dirs?y.dirs.concat(n.dirs):n.dirs),n.transition&&(y.transition=n.transition),w=y,Pr(S),w}const Lu=e=>{let t;for(const n in e)(n==="class"||n==="style"||Xn(n))&&((t||(t={}))[n]=e[n]);return t},Ru=(e,t)=>{const n={};for(const r in e)(!Go(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Iu(e,t,n){const{props:r,children:o,component:s}=e,{props:l,children:a,patchFlag:c}=t,i=s.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?Bs(r,l,i):!!l;if(c&8){const u=t.dynamicProps;for(let d=0;de.__isSuspense;function xa(e,t){t&&t.pendingBranch?X(e)?t.effects.push(...e):t.effects.push(e):Su(e)}const Nu=Symbol.for("v-scx"),Du=()=>Le(Nu);function Sa(e,t){return as(e,null,t)}const gr={};function ie(e,t,n){return as(e,t,n)}function as(e,t,{immediate:n,deep:r,flush:o,once:s,onTrack:l,onTrigger:a}=ve){if(t&&s){const C=t;t=(...M)=>{C(...M),$()}}const c=ke,i=C=>r===!0?C:rn(C,r===!1?1:void 0);let u,d=!1,p=!1;if(Ie(e)?(u=()=>e.value,d=Rr(e)):an(e)?(u=()=>i(e),d=!0):X(e)?(p=!0,d=e.some(C=>an(C)||Rr(C)),u=()=>e.map(C=>{if(Ie(C))return C.value;if(an(C))return i(C);if(ee(C))return Pt(C,c,2)})):ee(e)?t?u=()=>Pt(e,c,2):u=()=>(m&&m(),Xe(e,c,3,[g])):u=Je,t&&r){const C=u;u=()=>rn(C())}let m,g=C=>{m=y.onStop=()=>{Pt(C,c,4),m=y.onStop=void 0}},E;if(or)if(g=Je,t?n&&Xe(t,c,3,[u(),p?[]:void 0,g]):u(),o==="sync"){const C=Du();E=C.__watcherHandles||(C.__watcherHandles=[])}else return Je;let w=p?new Array(e.length).fill(gr):gr;const b=()=>{if(!(!y.active||!y.dirty))if(t){const C=y.run();(r||d||(p?C.some((M,I)=>Ot(M,w[I])):Ot(C,w)))&&(m&&m(),Xe(t,c,3,[C,w===gr?void 0:p&&w[0]===gr?[]:w,g]),w=C)}else y.run()};b.allowRecurse=!!t;let S;o==="sync"?S=b:o==="post"?S=()=>Be(b,c&&c.suspense):(b.pre=!0,c&&(b.id=c.uid),S=()=>zr(b));const y=new Xo(u,Je,S),x=Zl(),$=()=>{y.stop(),x&&Ko(x.effects,y)};return t?n?b():w=y.run():o==="post"?Be(y.run.bind(y),c&&c.suspense):y.run(),E&&E.push($),$}function Fu(e,t,n){const r=this.proxy,o=Ae(e)?e.includes(".")?Ta(r,e):()=>r[e]:e.bind(r,r);let s;ee(t)?s=t:(s=t.handler,n=t);const l=rr(this),a=as(o,s.bind(r),n);return l(),a}function Ta(e,t){const n=t.split(".");return()=>{let r=e;for(let o=0;o0){if(n>=t)return e;n++}if(r=r||new Set,r.has(e))return e;if(r.add(e),Ie(e))rn(e.value,t,n,r);else if(X(e))for(let o=0;o{rn(o,t,n,r)});else if($c(e))for(const o in e)rn(e[o],t,n,r);return e}function ct(e,t,n,r){const o=e.dirs,s=t&&t.dirs;for(let l=0;l{e.isMounted=!0}),Pa(()=>{e.isUnmounting=!0}),e}const Ke=[Function,Array],Aa={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Ke,onEnter:Ke,onAfterEnter:Ke,onEnterCancelled:Ke,onBeforeLeave:Ke,onLeave:Ke,onAfterLeave:Ke,onLeaveCancelled:Ke,onBeforeAppear:Ke,onAppear:Ke,onAfterAppear:Ke,onAppearCancelled:Ke},Hu={name:"BaseTransition",props:Aa,setup(e,{slots:t}){const n=Cn(),r=ka();let o;return()=>{const s=t.default&&is(t.default(),!0);if(!s||!s.length)return;let l=s[0];if(s.length>1){for(const E of s)if(E.type!==ft){l=E;break}}const a=oe(e),{mode:c}=a;if(r.isLeaving)return oo(l);const i=Vs(l);if(!i)return oo(l);const u=Un(i,a,r,n);qn(i,u);const d=n.subTree,p=d&&Vs(d);let m=!1;const{getTransitionKey:g}=i.type;if(g){const E=g();o===void 0?o=E:E!==o&&(o=E,m=!0)}if(p&&p.type!==ft&&(!zt(i,p)||m)){const E=Un(p,a,r,n);if(qn(p,E),c==="out-in")return r.isLeaving=!0,E.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&(n.effect.dirty=!0,n.update())},oo(l);c==="in-out"&&i.type!==ft&&(E.delayLeave=(w,b,S)=>{const y=La(r,p);y[String(p.key)]=p,w[kt]=()=>{b(),w[kt]=void 0,delete u.delayedLeave},u.delayedLeave=S})}return l}}},Bu=Hu;function La(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Un(e,t,n,r){const{appear:o,mode:s,persisted:l=!1,onBeforeEnter:a,onEnter:c,onAfterEnter:i,onEnterCancelled:u,onBeforeLeave:d,onLeave:p,onAfterLeave:m,onLeaveCancelled:g,onBeforeAppear:E,onAppear:w,onAfterAppear:b,onAppearCancelled:S}=t,y=String(e.key),x=La(n,e),$=(I,D)=>{I&&Xe(I,r,9,D)},C=(I,D)=>{const F=D[1];$(I,D),X(I)?I.every(Z=>Z.length<=1)&&F():I.length<=1&&F()},M={mode:s,persisted:l,beforeEnter(I){let D=a;if(!n.isMounted)if(o)D=E||a;else return;I[kt]&&I[kt](!0);const F=x[y];F&&zt(e,F)&&F.el[kt]&&F.el[kt](),$(D,[I])},enter(I){let D=c,F=i,Z=u;if(!n.isMounted)if(o)D=w||c,F=b||i,Z=S||u;else return;let H=!1;const J=I[br]=be=>{H||(H=!0,be?$(Z,[I]):$(F,[I]),M.delayedLeave&&M.delayedLeave(),I[br]=void 0)};D?C(D,[I,J]):J()},leave(I,D){const F=String(e.key);if(I[br]&&I[br](!0),n.isUnmounting)return D();$(d,[I]);let Z=!1;const H=I[kt]=J=>{Z||(Z=!0,D(),J?$(g,[I]):$(m,[I]),I[kt]=void 0,x[F]===e&&delete x[F])};x[F]=e,p?C(p,[I,H]):H()},clone(I){return Un(I,t,n,r)}};return M}function oo(e){if(nr(e))return e=Mt(e),e.children=null,e}function Vs(e){return nr(e)?e.children?e.children[0]:void 0:e}function qn(e,t){e.shapeFlag&6&&e.component?qn(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function is(e,t=!1,n){let r=[],o=0;for(let s=0;s1)for(let s=0;s!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function ju(e){ee(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:o=200,timeout:s,suspensible:l=!0,onError:a}=e;let c=null,i,u=0;const d=()=>(u++,c=null,p()),p=()=>{let m;return c||(m=c=t().catch(g=>{if(g=g instanceof Error?g:new Error(String(g)),a)return new Promise((E,w)=>{a(g,()=>E(d()),()=>w(g),u+1)});throw g}).then(g=>m!==c&&c?c:(g&&(g.__esModule||g[Symbol.toStringTag]==="Module")&&(g=g.default),i=g,g)))};return q({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return i},setup(){const m=ke;if(i)return()=>so(i,m);const g=S=>{c=null,tr(S,m,13,!r)};if(l&&m.suspense||or)return p().then(S=>()=>so(S,m)).catch(S=>(g(S),()=>r?Ce(r,{error:S}):null));const E=te(!1),w=te(),b=te(!!o);return o&&setTimeout(()=>{b.value=!1},o),s!=null&&setTimeout(()=>{if(!E.value&&!w.value){const S=new Error(`Async component timed out after ${s}ms.`);g(S),w.value=S}},s),p().then(()=>{E.value=!0,m.parent&&nr(m.parent.vnode)&&(m.parent.effect.dirty=!0,zr(m.parent.update))}).catch(S=>{g(S),w.value=S}),()=>{if(E.value&&i)return so(i,m);if(w.value&&r)return Ce(r,{error:w.value});if(n&&!b.value)return Ce(n)}}})}function so(e,t){const{ref:n,props:r,children:o,ce:s}=t.vnode,l=Ce(e,r,o);return l.ref=n,l.ce=s,delete t.vnode.ce,l}const nr=e=>e.type.__isKeepAlive;function Vu(e,t){Ra(e,"a",t)}function zu(e,t){Ra(e,"da",t)}function Ra(e,t,n=ke){const r=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Ur(t,r,n),n){let o=n.parent;for(;o&&o.parent;)nr(o.parent.vnode)&&Wu(r,t,n,o),o=o.parent}}function Wu(e,t,n,r){const o=Ur(t,e,r,!0);En(()=>{Ko(r[t],o)},n)}function Ur(e,t,n=ke,r=!1){if(n){const o=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...l)=>{if(n.isUnmounted)return;Yt();const a=rr(n),c=Xe(t,n,e,l);return a(),Jt(),c});return r?o.unshift(s):o.push(s),s}}const yt=e=>(t,n=ke)=>(!or||e==="sp")&&Ur(e,(...r)=>t(...r),n),Uu=yt("bm"),_e=yt("m"),qu=yt("bu"),Ia=yt("u"),Pa=yt("bum"),En=yt("um"),Gu=yt("sp"),Ku=yt("rtg"),Yu=yt("rtc");function Ju(e,t=ke){Ur("ec",e,t)}const Lo=e=>e?qa(e)?ds(e)||e.proxy:Lo(e.parent):null,Nn=we(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Lo(e.parent),$root:e=>Lo(e.root),$emit:e=>e.emit,$options:e=>cs(e),$forceUpdate:e=>e.f||(e.f=()=>{e.effect.dirty=!0,zr(e.update)}),$nextTick:e=>e.n||(e.n=Qt.bind(e.proxy)),$watch:e=>Fu.bind(e)}),lo=(e,t)=>e!==ve&&!e.__isScriptSetup&&le(e,t),Qu={get({_:e},t){const{ctx:n,setupState:r,data:o,props:s,accessCache:l,type:a,appContext:c}=e;let i;if(t[0]!=="$"){const m=l[t];if(m!==void 0)switch(m){case 1:return r[t];case 2:return o[t];case 4:return n[t];case 3:return s[t]}else{if(lo(r,t))return l[t]=1,r[t];if(o!==ve&&le(o,t))return l[t]=2,o[t];if((i=e.propsOptions[0])&&le(i,t))return l[t]=3,s[t];if(n!==ve&&le(n,t))return l[t]=4,n[t];Ro&&(l[t]=0)}}const u=Nn[t];let d,p;if(u)return t==="$attrs"&&We(e,"get",t),u(e);if((d=a.__cssModules)&&(d=d[t]))return d;if(n!==ve&&le(n,t))return l[t]=4,n[t];if(p=c.config.globalProperties,le(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:o,ctx:s}=e;return lo(o,t)?(o[t]=n,!0):r!==ve&&le(r,t)?(r[t]=n,!0):le(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(s[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:o,propsOptions:s}},l){let a;return!!n[l]||e!==ve&&le(e,l)||lo(t,l)||(a=s[0])&&le(a,l)||le(r,l)||le(Nn,l)||le(o.config.globalProperties,l)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:le(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function zs(e){return X(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Ro=!0;function Xu(e){const t=cs(e),n=e.proxy,r=e.ctx;Ro=!1,t.beforeCreate&&Ws(t.beforeCreate,e,"bc");const{data:o,computed:s,methods:l,watch:a,provide:c,inject:i,created:u,beforeMount:d,mounted:p,beforeUpdate:m,updated:g,activated:E,deactivated:w,beforeDestroy:b,beforeUnmount:S,destroyed:y,unmounted:x,render:$,renderTracked:C,renderTriggered:M,errorCaptured:I,serverPrefetch:D,expose:F,inheritAttrs:Z,components:H,directives:J,filters:be}=t;if(i&&Zu(i,r,null),l)for(const ne in l){const U=l[ne];ee(U)&&(r[ne]=U.bind(n))}if(o){const ne=o.call(n,n);me(ne)&&(e.data=Zn(ne))}if(Ro=!0,s)for(const ne in s){const U=s[ne],Ze=ee(U)?U.bind(n,n):ee(U.get)?U.get.bind(n,n):Je,wt=!ee(U)&&ee(U.set)?U.set.bind(n):Je,at=k({get:Ze,set:wt});Object.defineProperty(r,ne,{enumerable:!0,configurable:!0,get:()=>at.value,set:He=>at.value=He})}if(a)for(const ne in a)Oa(a[ne],r,n,ne);if(c){const ne=ee(c)?c.call(n):c;Reflect.ownKeys(ne).forEach(U=>{un(U,ne[U])})}u&&Ws(u,e,"c");function G(ne,U){X(U)?U.forEach(Ze=>ne(Ze.bind(n))):U&&ne(U.bind(n))}if(G(Uu,d),G(_e,p),G(qu,m),G(Ia,g),G(Vu,E),G(zu,w),G(Ju,I),G(Yu,C),G(Ku,M),G(Pa,S),G(En,x),G(Gu,D),X(F))if(F.length){const ne=e.exposed||(e.exposed={});F.forEach(U=>{Object.defineProperty(ne,U,{get:()=>n[U],set:Ze=>n[U]=Ze})})}else e.exposed||(e.exposed={});$&&e.render===Je&&(e.render=$),Z!=null&&(e.inheritAttrs=Z),H&&(e.components=H),J&&(e.directives=J)}function Zu(e,t,n=Je){X(e)&&(e=Io(e));for(const r in e){const o=e[r];let s;me(o)?"default"in o?s=Le(o.from||r,o.default,!0):s=Le(o.from||r):s=Le(o),Ie(s)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>s.value,set:l=>s.value=l}):t[r]=s}}function Ws(e,t,n){Xe(X(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function Oa(e,t,n,r){const o=r.includes(".")?Ta(n,r):()=>n[r];if(Ae(e)){const s=t[e];ee(s)&&ie(o,s)}else if(ee(e))ie(o,e.bind(n));else if(me(e))if(X(e))e.forEach(s=>Oa(s,t,n,r));else{const s=ee(e.handler)?e.handler.bind(n):t[e.handler];ee(s)&&ie(o,s,e)}}function cs(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:o,optionsCache:s,config:{optionMergeStrategies:l}}=e.appContext,a=s.get(t);let c;return a?c=a:!o.length&&!n&&!r?c=t:(c={},o.length&&o.forEach(i=>Or(c,i,l,!0)),Or(c,t,l)),me(t)&&s.set(t,c),c}function Or(e,t,n,r=!1){const{mixins:o,extends:s}=t;s&&Or(e,s,n,!0),o&&o.forEach(l=>Or(e,l,n,!0));for(const l in t)if(!(r&&l==="expose")){const a=ef[l]||n&&n[l];e[l]=a?a(e[l],t[l]):t[l]}return e}const ef={data:Us,props:qs,emits:qs,methods:In,computed:In,beforeCreate:$e,created:$e,beforeMount:$e,mounted:$e,beforeUpdate:$e,updated:$e,beforeDestroy:$e,beforeUnmount:$e,destroyed:$e,unmounted:$e,activated:$e,deactivated:$e,errorCaptured:$e,serverPrefetch:$e,components:In,directives:In,watch:nf,provide:Us,inject:tf};function Us(e,t){return t?e?function(){return we(ee(e)?e.call(this,this):e,ee(t)?t.call(this,this):t)}:t:e}function tf(e,t){return In(Io(e),Io(t))}function Io(e){if(X(e)){const t={};for(let n=0;n1)return n&&ee(t)?t.call(r&&r.proxy):t}}function sf(e,t,n,r=!1){const o={},s={};Ar(s,qr,1),e.propsDefaults=Object.create(null),$a(e,t,o,s);for(const l in e.propsOptions[0])l in o||(o[l]=void 0);n?e.props=r?o:fa(o):e.type.props?e.props=o:e.props=s,e.attrs=s}function lf(e,t,n,r){const{props:o,attrs:s,vnode:{patchFlag:l}}=e,a=oe(o),[c]=e.propsOptions;let i=!1;if((r||l>0)&&!(l&16)){if(l&8){const u=e.vnode.dynamicProps;for(let d=0;d{c=!0;const[p,m]=Na(d,t,!0);we(l,p),m&&a.push(...m)};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!s&&!c)return me(e)&&r.set(e,sn),sn;if(X(s))for(let u=0;u-1,m[1]=E<0||g-1||le(m,"default"))&&a.push(d)}}}const i=[l,a];return me(e)&&r.set(e,i),i}function Gs(e){return e[0]!=="$"&&!ln(e)}function Ks(e){return e===null?"null":typeof e=="function"?e.name||"":typeof e=="object"&&e.constructor&&e.constructor.name||""}function Ys(e,t){return Ks(e)===Ks(t)}function Js(e,t){return X(t)?t.findIndex(n=>Ys(n,e)):ee(t)&&Ys(t,e)?0:-1}const Da=e=>e[0]==="_"||e==="$stable",us=e=>X(e)?e.map(tt):[tt(e)],af=(e,t,n)=>{if(t._n)return t;const r=Au((...o)=>us(t(...o)),n);return r._c=!1,r},Fa=(e,t,n)=>{const r=e._ctx;for(const o in e){if(Da(o))continue;const s=e[o];if(ee(s))t[o]=af(o,s,r);else if(s!=null){const l=us(s);t[o]=()=>l}}},Ha=(e,t)=>{const n=us(t);e.slots.default=()=>n},cf=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=oe(t),Ar(t,"_",n)):Fa(t,e.slots={})}else e.slots={},t&&Ha(e,t);Ar(e.slots,qr,1)},uf=(e,t,n)=>{const{vnode:r,slots:o}=e;let s=!0,l=ve;if(r.shapeFlag&32){const a=t._;a?n&&a===1?s=!1:(we(o,t),!n&&a===1&&delete o._):(s=!t.$stable,Fa(t,o)),l=t}else t&&(Ha(e,t),l={default:1});if(s)for(const a in o)!Da(a)&&l[a]==null&&delete o[a]};function Mr(e,t,n,r,o=!1){if(X(e)){e.forEach((p,m)=>Mr(p,t&&(X(t)?t[m]:t),n,r,o));return}if($n(r)&&!o)return;const s=r.shapeFlag&4?ds(r.component)||r.component.proxy:r.el,l=o?null:s,{i:a,r:c}=e,i=t&&t.r,u=a.refs===ve?a.refs={}:a.refs,d=a.setupState;if(i!=null&&i!==c&&(Ae(i)?(u[i]=null,le(d,i)&&(d[i]=null)):Ie(i)&&(i.value=null)),ee(c))Pt(c,a,12,[l,u]);else{const p=Ae(c),m=Ie(c);if(p||m){const g=()=>{if(e.f){const E=p?le(d,c)?d[c]:u[c]:c.value;o?X(E)&&Ko(E,s):X(E)?E.includes(s)||E.push(s):p?(u[c]=[s],le(d,c)&&(d[c]=u[c])):(c.value=[s],e.k&&(u[e.k]=c.value))}else p?(u[c]=l,le(d,c)&&(d[c]=l)):m&&(c.value=l,e.k&&(u[e.k]=l))};l?(g.id=-1,Be(g,n)):g()}}}let Ct=!1;const ff=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",df=e=>e.namespaceURI.includes("MathML"),yr=e=>{if(ff(e))return"svg";if(df(e))return"mathml"},_r=e=>e.nodeType===8;function pf(e){const{mt:t,p:n,o:{patchProp:r,createText:o,nextSibling:s,parentNode:l,remove:a,insert:c,createComment:i}}=e,u=(y,x)=>{if(!x.hasChildNodes()){n(null,y,x),Ir(),x._vnode=y;return}Ct=!1,d(x.firstChild,y,null,null,null),Ir(),x._vnode=y,Ct&&console.error("Hydration completed but contains mismatches.")},d=(y,x,$,C,M,I=!1)=>{const D=_r(y)&&y.data==="[",F=()=>E(y,x,$,C,M,D),{type:Z,ref:H,shapeFlag:J,patchFlag:be}=x;let ye=y.nodeType;x.el=y,be===-2&&(I=!1,x.dynamicChildren=null);let G=null;switch(Z){case hn:ye!==3?x.children===""?(c(x.el=o(""),l(y),y),G=y):G=F():(y.data!==x.children&&(Ct=!0,y.data=x.children),G=s(y));break;case ft:S(y)?(G=s(y),b(x.el=y.content.firstChild,y,$)):ye!==8||D?G=F():G=s(y);break;case Fn:if(D&&(y=s(y),ye=y.nodeType),ye===1||ye===3){G=y;const ne=!x.children.length;for(let U=0;U{I=I||!!x.dynamicChildren;const{type:D,props:F,patchFlag:Z,shapeFlag:H,dirs:J,transition:be}=x,ye=D==="input"||D==="option";if(ye||Z!==-1){J&&ct(x,null,$,"created");let G=!1;if(S(y)){G=Ba(C,be)&&$&&$.vnode.props&&$.vnode.props.appear;const U=y.content.firstChild;G&&be.beforeEnter(U),b(U,y,$),x.el=y=U}if(H&16&&!(F&&(F.innerHTML||F.textContent))){let U=m(y.firstChild,x,y,$,C,M,I);for(;U;){Ct=!0;const Ze=U;U=U.nextSibling,a(Ze)}}else H&8&&y.textContent!==x.children&&(Ct=!0,y.textContent=x.children);if(F)if(ye||!I||Z&48)for(const U in F)(ye&&(U.endsWith("value")||U==="indeterminate")||Xn(U)&&!ln(U)||U[0]===".")&&r(y,U,null,F[U],void 0,void 0,$);else F.onClick&&r(y,"onClick",null,F.onClick,void 0,void 0,$);let ne;(ne=F&&F.onVnodeBeforeMount)&&Ye(ne,$,x),J&&ct(x,null,$,"beforeMount"),((ne=F&&F.onVnodeMounted)||J||G)&&xa(()=>{ne&&Ye(ne,$,x),G&&be.enter(y),J&&ct(x,null,$,"mounted")},C)}return y.nextSibling},m=(y,x,$,C,M,I,D)=>{D=D||!!x.dynamicChildren;const F=x.children,Z=F.length;for(let H=0;H{const{slotScopeIds:D}=x;D&&(M=M?M.concat(D):D);const F=l(y),Z=m(s(y),x,F,$,C,M,I);return Z&&_r(Z)&&Z.data==="]"?s(x.anchor=Z):(Ct=!0,c(x.anchor=i("]"),F,Z),Z)},E=(y,x,$,C,M,I)=>{if(Ct=!0,x.el=null,I){const Z=w(y);for(;;){const H=s(y);if(H&&H!==Z)a(H);else break}}const D=s(y),F=l(y);return a(y),n(null,x,F,D,$,C,yr(F),M),D},w=(y,x="[",$="]")=>{let C=0;for(;y;)if(y=s(y),y&&_r(y)&&(y.data===x&&C++,y.data===$)){if(C===0)return s(y);C--}return y},b=(y,x,$)=>{const C=x.parentNode;C&&C.replaceChild(y,x);let M=$;for(;M;)M.vnode.el===x&&(M.vnode.el=M.subTree.el=y),M=M.parent},S=y=>y.nodeType===1&&y.tagName.toLowerCase()==="template";return[u,d]}const Be=xa;function hf(e){return vf(e,pf)}function vf(e,t){const n=Ql();n.__VUE__=!0;const{insert:r,remove:o,patchProp:s,createElement:l,createText:a,createComment:c,setText:i,setElementText:u,parentNode:d,nextSibling:p,setScopeId:m=Je,insertStaticContent:g}=e,E=(h,v,_,L=null,T=null,O=null,j=void 0,P=null,N=!!v.dynamicChildren)=>{if(h===v)return;h&&!zt(h,v)&&(L=A(h),He(h,T,O,!0),h=null),v.patchFlag===-2&&(N=!1,v.dynamicChildren=null);const{type:R,ref:z,shapeFlag:Y}=v;switch(R){case hn:w(h,v,_,L);break;case ft:b(h,v,_,L);break;case Fn:h==null&&S(v,_,L,j);break;case Ge:H(h,v,_,L,T,O,j,P,N);break;default:Y&1?$(h,v,_,L,T,O,j,P,N):Y&6?J(h,v,_,L,T,O,j,P,N):(Y&64||Y&128)&&R.process(h,v,_,L,T,O,j,P,N,W)}z!=null&&T&&Mr(z,h&&h.ref,O,v||h,!v)},w=(h,v,_,L)=>{if(h==null)r(v.el=a(v.children),_,L);else{const T=v.el=h.el;v.children!==h.children&&i(T,v.children)}},b=(h,v,_,L)=>{h==null?r(v.el=c(v.children||""),_,L):v.el=h.el},S=(h,v,_,L)=>{[h.el,h.anchor]=g(h.children,v,_,L,h.el,h.anchor)},y=({el:h,anchor:v},_,L)=>{let T;for(;h&&h!==v;)T=p(h),r(h,_,L),h=T;r(v,_,L)},x=({el:h,anchor:v})=>{let _;for(;h&&h!==v;)_=p(h),o(h),h=_;o(v)},$=(h,v,_,L,T,O,j,P,N)=>{v.type==="svg"?j="svg":v.type==="math"&&(j="mathml"),h==null?C(v,_,L,T,O,j,P,N):D(h,v,T,O,j,P,N)},C=(h,v,_,L,T,O,j,P)=>{let N,R;const{props:z,shapeFlag:Y,transition:K,dirs:Q}=h;if(N=h.el=l(h.type,O,z&&z.is,z),Y&8?u(N,h.children):Y&16&&I(h.children,N,null,L,T,ao(h,O),j,P),Q&&ct(h,null,L,"created"),M(N,h,h.scopeId,j,L),z){for(const ue in z)ue!=="value"&&!ln(ue)&&s(N,ue,null,z[ue],O,h.children,L,T,Oe);"value"in z&&s(N,"value",null,z.value,O),(R=z.onVnodeBeforeMount)&&Ye(R,L,h)}Q&&ct(h,null,L,"beforeMount");const re=Ba(T,K);re&&K.beforeEnter(N),r(N,v,_),((R=z&&z.onVnodeMounted)||re||Q)&&Be(()=>{R&&Ye(R,L,h),re&&K.enter(N),Q&&ct(h,null,L,"mounted")},T)},M=(h,v,_,L,T)=>{if(_&&m(h,_),L)for(let O=0;O{for(let R=N;R{const P=v.el=h.el;let{patchFlag:N,dynamicChildren:R,dirs:z}=v;N|=h.patchFlag&16;const Y=h.props||ve,K=v.props||ve;let Q;if(_&&Ht(_,!1),(Q=K.onVnodeBeforeUpdate)&&Ye(Q,_,v,h),z&&ct(v,h,_,"beforeUpdate"),_&&Ht(_,!0),R?F(h.dynamicChildren,R,P,_,L,ao(v,T),O):j||U(h,v,P,null,_,L,ao(v,T),O,!1),N>0){if(N&16)Z(P,v,Y,K,_,L,T);else if(N&2&&Y.class!==K.class&&s(P,"class",null,K.class,T),N&4&&s(P,"style",Y.style,K.style,T),N&8){const re=v.dynamicProps;for(let ue=0;ue{Q&&Ye(Q,_,v,h),z&&ct(v,h,_,"updated")},L)},F=(h,v,_,L,T,O,j)=>{for(let P=0;P{if(_!==L){if(_!==ve)for(const P in _)!ln(P)&&!(P in L)&&s(h,P,_[P],null,j,v.children,T,O,Oe);for(const P in L){if(ln(P))continue;const N=L[P],R=_[P];N!==R&&P!=="value"&&s(h,P,R,N,j,v.children,T,O,Oe)}"value"in L&&s(h,"value",_.value,L.value,j)}},H=(h,v,_,L,T,O,j,P,N)=>{const R=v.el=h?h.el:a(""),z=v.anchor=h?h.anchor:a("");let{patchFlag:Y,dynamicChildren:K,slotScopeIds:Q}=v;Q&&(P=P?P.concat(Q):Q),h==null?(r(R,_,L),r(z,_,L),I(v.children||[],_,z,T,O,j,P,N)):Y>0&&Y&64&&K&&h.dynamicChildren?(F(h.dynamicChildren,K,_,T,O,j,P),(v.key!=null||T&&v===T.subTree)&&ja(h,v,!0)):U(h,v,_,z,T,O,j,P,N)},J=(h,v,_,L,T,O,j,P,N)=>{v.slotScopeIds=P,h==null?v.shapeFlag&512?T.ctx.activate(v,_,L,j,N):be(v,_,L,T,O,j,N):ye(h,v,N)},be=(h,v,_,L,T,O,j)=>{const P=h.component=Sf(h,L,T);if(nr(h)&&(P.ctx.renderer=W),Tf(P),P.asyncDep){if(T&&T.registerDep(P,G),!h.el){const N=P.subTree=Ce(ft);b(null,N,v,_)}}else G(P,h,v,_,T,O,j)},ye=(h,v,_)=>{const L=v.component=h.component;if(Iu(h,v,_))if(L.asyncDep&&!L.asyncResolved){ne(L,v,_);return}else L.next=v,xu(L.update),L.effect.dirty=!0,L.update();else v.el=h.el,L.vnode=v},G=(h,v,_,L,T,O,j)=>{const P=()=>{if(h.isMounted){let{next:z,bu:Y,u:K,parent:Q,vnode:re}=h;{const tn=Va(h);if(tn){z&&(z.el=re.el,ne(h,z,j)),tn.asyncDep.then(()=>{h.isUnmounted||P()});return}}let ue=z,he;Ht(h,!1),z?(z.el=re.el,ne(h,z,j)):z=re,Y&&no(Y),(he=z.props&&z.props.onVnodeBeforeUpdate)&&Ye(he,Q,z,re),Ht(h,!0);const Te=ro(h),et=h.subTree;h.subTree=Te,E(et,Te,d(et.el),A(et),h,T,O),z.el=Te.el,ue===null&&Pu(h,Te.el),K&&Be(K,T),(he=z.props&&z.props.onVnodeUpdated)&&Be(()=>Ye(he,Q,z,re),T)}else{let z;const{el:Y,props:K}=v,{bm:Q,m:re,parent:ue}=h,he=$n(v);if(Ht(h,!1),Q&&no(Q),!he&&(z=K&&K.onVnodeBeforeMount)&&Ye(z,ue,v),Ht(h,!0),Y&&pe){const Te=()=>{h.subTree=ro(h),pe(Y,h.subTree,h,T,null)};he?v.type.__asyncLoader().then(()=>!h.isUnmounted&&Te()):Te()}else{const Te=h.subTree=ro(h);E(null,Te,_,L,h,T,O),v.el=Te.el}if(re&&Be(re,T),!he&&(z=K&&K.onVnodeMounted)){const Te=v;Be(()=>Ye(z,ue,Te),T)}(v.shapeFlag&256||ue&&$n(ue.vnode)&&ue.vnode.shapeFlag&256)&&h.a&&Be(h.a,T),h.isMounted=!0,v=_=L=null}},N=h.effect=new Xo(P,Je,()=>zr(R),h.scope),R=h.update=()=>{N.dirty&&N.run()};R.id=h.uid,Ht(h,!0),R()},ne=(h,v,_)=>{v.component=h;const L=h.vnode.props;h.vnode=v,h.next=null,lf(h,v.props,L,_),uf(h,v.children,_),Yt(),Hs(h),Jt()},U=(h,v,_,L,T,O,j,P,N=!1)=>{const R=h&&h.children,z=h?h.shapeFlag:0,Y=v.children,{patchFlag:K,shapeFlag:Q}=v;if(K>0){if(K&128){wt(R,Y,_,L,T,O,j,P,N);return}else if(K&256){Ze(R,Y,_,L,T,O,j,P,N);return}}Q&8?(z&16&&Oe(R,T,O),Y!==R&&u(_,Y)):z&16?Q&16?wt(R,Y,_,L,T,O,j,P,N):Oe(R,T,O,!0):(z&8&&u(_,""),Q&16&&I(Y,_,L,T,O,j,P,N))},Ze=(h,v,_,L,T,O,j,P,N)=>{h=h||sn,v=v||sn;const R=h.length,z=v.length,Y=Math.min(R,z);let K;for(K=0;Kz?Oe(h,T,O,!0,!1,Y):I(v,_,L,T,O,j,P,N,Y)},wt=(h,v,_,L,T,O,j,P,N)=>{let R=0;const z=v.length;let Y=h.length-1,K=z-1;for(;R<=Y&&R<=K;){const Q=h[R],re=v[R]=N?At(v[R]):tt(v[R]);if(zt(Q,re))E(Q,re,_,null,T,O,j,P,N);else break;R++}for(;R<=Y&&R<=K;){const Q=h[Y],re=v[K]=N?At(v[K]):tt(v[K]);if(zt(Q,re))E(Q,re,_,null,T,O,j,P,N);else break;Y--,K--}if(R>Y){if(R<=K){const Q=K+1,re=QK)for(;R<=Y;)He(h[R],T,O,!0),R++;else{const Q=R,re=R,ue=new Map;for(R=re;R<=K;R++){const Ue=v[R]=N?At(v[R]):tt(v[R]);Ue.key!=null&&ue.set(Ue.key,R)}let he,Te=0;const et=K-re+1;let tn=!1,As=0;const kn=new Array(et);for(R=0;R=et){He(Ue,T,O,!0);continue}let it;if(Ue.key!=null)it=ue.get(Ue.key);else for(he=re;he<=K;he++)if(kn[he-re]===0&&zt(Ue,v[he])){it=he;break}it===void 0?He(Ue,T,O,!0):(kn[it-re]=R+1,it>=As?As=it:tn=!0,E(Ue,v[it],_,null,T,O,j,P,N),Te++)}const Ls=tn?mf(kn):sn;for(he=Ls.length-1,R=et-1;R>=0;R--){const Ue=re+R,it=v[Ue],Rs=Ue+1{const{el:O,type:j,transition:P,children:N,shapeFlag:R}=h;if(R&6){at(h.component.subTree,v,_,L);return}if(R&128){h.suspense.move(v,_,L);return}if(R&64){j.move(h,v,_,W);return}if(j===Ge){r(O,v,_);for(let Y=0;YP.enter(O),T);else{const{leave:Y,delayLeave:K,afterLeave:Q}=P,re=()=>r(O,v,_),ue=()=>{Y(O,()=>{re(),Q&&Q()})};K?K(O,re,ue):ue()}else r(O,v,_)},He=(h,v,_,L=!1,T=!1)=>{const{type:O,props:j,ref:P,children:N,dynamicChildren:R,shapeFlag:z,patchFlag:Y,dirs:K}=h;if(P!=null&&Mr(P,null,_,h,!0),z&256){v.ctx.deactivate(h);return}const Q=z&1&&K,re=!$n(h);let ue;if(re&&(ue=j&&j.onVnodeBeforeUnmount)&&Ye(ue,v,h),z&6)fr(h.component,_,L);else{if(z&128){h.suspense.unmount(_,L);return}Q&&ct(h,null,v,"beforeUnmount"),z&64?h.type.remove(h,v,_,T,W,L):R&&(O!==Ge||Y>0&&Y&64)?Oe(R,v,_,!1,!0):(O===Ge&&Y&384||!T&&z&16)&&Oe(N,v,_),L&&Zt(h)}(re&&(ue=j&&j.onVnodeUnmounted)||Q)&&Be(()=>{ue&&Ye(ue,v,h),Q&&ct(h,null,v,"unmounted")},_)},Zt=h=>{const{type:v,el:_,anchor:L,transition:T}=h;if(v===Ge){en(_,L);return}if(v===Fn){x(h);return}const O=()=>{o(_),T&&!T.persisted&&T.afterLeave&&T.afterLeave()};if(h.shapeFlag&1&&T&&!T.persisted){const{leave:j,delayLeave:P}=T,N=()=>j(_,O);P?P(h.el,O,N):N()}else O()},en=(h,v)=>{let _;for(;h!==v;)_=p(h),o(h),h=_;o(v)},fr=(h,v,_)=>{const{bum:L,scope:T,update:O,subTree:j,um:P}=h;L&&no(L),T.stop(),O&&(O.active=!1,He(j,h,v,_)),P&&Be(P,v),Be(()=>{h.isUnmounted=!0},v),v&&v.pendingBranch&&!v.isUnmounted&&h.asyncDep&&!h.asyncResolved&&h.suspenseId===v.pendingId&&(v.deps--,v.deps===0&&v.resolve())},Oe=(h,v,_,L=!1,T=!1,O=0)=>{for(let j=O;jh.shapeFlag&6?A(h.component.subTree):h.shapeFlag&128?h.suspense.next():p(h.anchor||h.el);let V=!1;const B=(h,v,_)=>{h==null?v._vnode&&He(v._vnode,null,null,!0):E(v._vnode||null,h,v,null,null,null,_),V||(V=!0,Hs(),Ir(),V=!1),v._vnode=h},W={p:E,um:He,m:at,r:Zt,mt:be,mc:I,pc:U,pbc:F,n:A,o:e};let ae,pe;return t&&([ae,pe]=t(W)),{render:B,hydrate:ae,createApp:of(B,ae)}}function ao({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Ht({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Ba(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function ja(e,t,n=!1){const r=e.children,o=t.children;if(X(r)&&X(o))for(let s=0;s>1,e[n[a]]0&&(t[r]=n[s-1]),n[s]=r)}}for(s=n.length,l=n[s-1];s-- >0;)n[s]=l,l=t[l];return n}function Va(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:Va(t)}const gf=e=>e.__isTeleport,Ge=Symbol.for("v-fgt"),hn=Symbol.for("v-txt"),ft=Symbol.for("v-cmt"),Fn=Symbol.for("v-stc"),Hn=[];let nt=null;function Xm(e=!1){Hn.push(nt=e?null:[])}function bf(){Hn.pop(),nt=Hn[Hn.length-1]||null}let Gn=1;function Qs(e){Gn+=e}function yf(e){return e.dynamicChildren=Gn>0?nt||sn:null,bf(),Gn>0&&nt&&nt.push(e),e}function Zm(e,t,n,r,o,s){return yf(Wa(e,t,n,r,o,s,!0))}function Oo(e){return e?e.__v_isVNode===!0:!1}function zt(e,t){return e.type===t.type&&e.key===t.key}const qr="__vInternal",za=({key:e})=>e??null,kr=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?Ae(e)||Ie(e)||ee(e)?{i:Qe,r:e,k:t,f:!!n}:e:null);function Wa(e,t=null,n=null,r=0,o=null,s=e===Ge?0:1,l=!1,a=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&za(t),ref:t&&kr(t),scopeId:Ea,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:Qe};return a?(fs(c,n),s&128&&e.normalize(c)):n&&(c.shapeFlag|=Ae(n)?8:16),Gn>0&&!l&&nt&&(c.patchFlag>0||s&6)&&c.patchFlag!==32&&nt.push(c),c}const Ce=_f;function _f(e,t=null,n=null,r=0,o=null,s=!1){if((!e||e===Ou)&&(e=ft),Oo(e)){const a=Mt(e,t,!0);return n&&fs(a,n),Gn>0&&!s&&nt&&(a.shapeFlag&6?nt[nt.indexOf(e)]=a:nt.push(a)),a.patchFlag|=-2,a}if(If(e)&&(e=e.__vccOpts),t){t=wf(t);let{class:a,style:c}=t;a&&!Ae(a)&&(t.class=Qo(a)),me(c)&&(da(c)&&!X(c)&&(c=we({},c)),t.style=Jo(c))}const l=Ae(e)?1:$u(e)?128:gf(e)?64:me(e)?4:ee(e)?2:0;return Wa(e,t,n,r,o,l,s,!0)}function wf(e){return e?da(e)||qr in e?we({},e):e:null}function Mt(e,t,n=!1){const{props:r,ref:o,patchFlag:s,children:l}=e,a=t?Ef(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:a,key:a&&za(a),ref:t&&t.ref?n&&o?X(o)?o.concat(kr(t)):[o,kr(t)]:kr(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Ge?s===-1?16:s|16:s,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Mt(e.ssContent),ssFallback:e.ssFallback&&Mt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function Ua(e=" ",t=0){return Ce(hn,null,e,t)}function eg(e,t){const n=Ce(Fn,null,e);return n.staticCount=t,n}function tt(e){return e==null||typeof e=="boolean"?Ce(ft):X(e)?Ce(Ge,null,e.slice()):typeof e=="object"?At(e):Ce(hn,null,String(e))}function At(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Mt(e)}function fs(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(X(t))n=16;else if(typeof t=="object")if(r&65){const o=t.default;o&&(o._c&&(o._d=!1),fs(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!(qr in t)?t._ctx=Qe:o===3&&Qe&&(Qe.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else ee(t)?(t={default:t,_ctx:Qe},n=32):(t=String(t),r&64?(n=16,t=[Ua(t)]):n=8);e.children=t,e.shapeFlag|=n}function Ef(...e){const t={};for(let n=0;nke||Qe;let $r,Mo;{const e=Ql(),t=(n,r)=>{let o;return(o=e[n])||(o=e[n]=[]),o.push(r),s=>{o.length>1?o.forEach(l=>l(s)):o[0](s)}};$r=t("__VUE_INSTANCE_SETTERS__",n=>ke=n),Mo=t("__VUE_SSR_SETTERS__",n=>or=n)}const rr=e=>{const t=ke;return $r(e),e.scope.on(),()=>{e.scope.off(),$r(t)}},Xs=()=>{ke&&ke.scope.off(),$r(null)};function qa(e){return e.vnode.shapeFlag&4}let or=!1;function Tf(e,t=!1){t&&Mo(t);const{props:n,children:r}=e.vnode,o=qa(e);sf(e,n,o,t),cf(e,r);const s=o?kf(e,t):void 0;return t&&Mo(!1),s}function kf(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=pa(new Proxy(e.ctx,Qu));const{setup:r}=n;if(r){const o=e.setupContext=r.length>1?Lf(e):null,s=rr(e);Yt();const l=Pt(r,e,0,[e.props,o]);if(Jt(),s(),Jl(l)){if(l.then(Xs,Xs),t)return l.then(a=>{Zs(e,a,t)}).catch(a=>{tr(a,e,0)});e.asyncDep=l}else Zs(e,l,t)}else Ga(e,t)}function Zs(e,t,n){ee(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:me(t)&&(e.setupState=ma(t)),Ga(e,n)}let el;function Ga(e,t,n){const r=e.type;if(!e.render){if(!t&&el&&!r.render){const o=r.template||cs(e).template;if(o){const{isCustomElement:s,compilerOptions:l}=e.appContext.config,{delimiters:a,compilerOptions:c}=r,i=we(we({isCustomElement:s,delimiters:a},l),c);r.render=el(o,i)}}e.render=r.render||Je}{const o=rr(e);Yt();try{Xu(e)}finally{Jt(),o()}}}function Af(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return We(e,"get","$attrs"),t[n]}}))}function Lf(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return Af(e)},slots:e.slots,emit:e.emit,expose:t}}function ds(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(ma(pa(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Nn)return Nn[n](e)},has(t,n){return n in t||n in Nn}}))}function Rf(e,t=!0){return ee(e)?e.displayName||e.name:e.name||t&&e.__name}function If(e){return ee(e)&&"__vccOpts"in e}const k=(e,t)=>vu(e,t,or);function f(e,t,n){const r=arguments.length;return r===2?me(t)&&!X(t)?Oo(t)?Ce(e,null,[t]):Ce(e,t):Ce(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Oo(n)&&(n=[n]),Ce(e,t,n))}const Pf="3.4.19";/** +* @vue/runtime-dom v3.4.19 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Of="http://www.w3.org/2000/svg",Mf="http://www.w3.org/1998/Math/MathML",Lt=typeof document<"u"?document:null,tl=Lt&&Lt.createElement("template"),$f={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o=t==="svg"?Lt.createElementNS(Of,e):t==="mathml"?Lt.createElementNS(Mf,e):Lt.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&o.setAttribute("multiple",r.multiple),o},createText:e=>Lt.createTextNode(e),createComment:e=>Lt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Lt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,s){const l=n?n.previousSibling:t.lastChild;if(o&&(o===s||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===s||!(o=o.nextSibling)););else{tl.innerHTML=r==="svg"?`${e}`:r==="mathml"?`${e}`:e;const a=tl.content;if(r==="svg"||r==="mathml"){const c=a.firstChild;for(;c.firstChild;)a.appendChild(c.firstChild);a.removeChild(c)}t.insertBefore(a,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},xt="transition",An="animation",vn=Symbol("_vtc"),$t=(e,{slots:t})=>f(Bu,Ya(e),t);$t.displayName="Transition";const Ka={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Nf=$t.props=we({},Aa,Ka),Bt=(e,t=[])=>{X(e)?e.forEach(n=>n(...t)):e&&e(...t)},nl=e=>e?X(e)?e.some(t=>t.length>1):e.length>1:!1;function Ya(e){const t={};for(const H in e)H in Ka||(t[H]=e[H]);if(e.css===!1)return t;const{name:n="v",type:r,duration:o,enterFromClass:s=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:a=`${n}-enter-to`,appearFromClass:c=s,appearActiveClass:i=l,appearToClass:u=a,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:m=`${n}-leave-to`}=e,g=Df(o),E=g&&g[0],w=g&&g[1],{onBeforeEnter:b,onEnter:S,onEnterCancelled:y,onLeave:x,onLeaveCancelled:$,onBeforeAppear:C=b,onAppear:M=S,onAppearCancelled:I=y}=t,D=(H,J,be)=>{St(H,J?u:a),St(H,J?i:l),be&&be()},F=(H,J)=>{H._isLeaving=!1,St(H,d),St(H,m),St(H,p),J&&J()},Z=H=>(J,be)=>{const ye=H?M:S,G=()=>D(J,H,be);Bt(ye,[J,G]),rl(()=>{St(J,H?c:s),ht(J,H?u:a),nl(ye)||ol(J,r,E,G)})};return we(t,{onBeforeEnter(H){Bt(b,[H]),ht(H,s),ht(H,l)},onBeforeAppear(H){Bt(C,[H]),ht(H,c),ht(H,i)},onEnter:Z(!1),onAppear:Z(!0),onLeave(H,J){H._isLeaving=!0;const be=()=>F(H,J);ht(H,d),Qa(),ht(H,p),rl(()=>{H._isLeaving&&(St(H,d),ht(H,m),nl(x)||ol(H,r,w,be))}),Bt(x,[H,be])},onEnterCancelled(H){D(H,!1),Bt(y,[H])},onAppearCancelled(H){D(H,!0),Bt(I,[H])},onLeaveCancelled(H){F(H),Bt($,[H])}})}function Df(e){if(e==null)return null;if(me(e))return[io(e.enter),io(e.leave)];{const t=io(e);return[t,t]}}function io(e){return Hc(e)}function ht(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[vn]||(e[vn]=new Set)).add(t)}function St(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[vn];n&&(n.delete(t),n.size||(e[vn]=void 0))}function rl(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Ff=0;function ol(e,t,n,r){const o=e._endId=++Ff,s=()=>{o===e._endId&&r()};if(n)return setTimeout(s,n);const{type:l,timeout:a,propCount:c}=Ja(e,t);if(!l)return r();const i=l+"end";let u=0;const d=()=>{e.removeEventListener(i,p),s()},p=m=>{m.target===e&&++u>=c&&d()};setTimeout(()=>{u(n[g]||"").split(", "),o=r(`${xt}Delay`),s=r(`${xt}Duration`),l=sl(o,s),a=r(`${An}Delay`),c=r(`${An}Duration`),i=sl(a,c);let u=null,d=0,p=0;t===xt?l>0&&(u=xt,d=l,p=s.length):t===An?i>0&&(u=An,d=i,p=c.length):(d=Math.max(l,i),u=d>0?l>i?xt:An:null,p=u?u===xt?s.length:c.length:0);const m=u===xt&&/\b(transform|all)(,|$)/.test(r(`${xt}Property`).toString());return{type:u,timeout:d,propCount:p,hasTransform:m}}function sl(e,t){for(;e.lengthll(n)+ll(e[r])))}function ll(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Qa(){return document.body.offsetHeight}function Hf(e,t,n){const r=e[vn];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const al=Symbol("_vod"),Bf=Symbol(""),jf=/(^|;)\s*display\s*:/;function Vf(e,t,n){const r=e.style,o=Ae(n),s=r.display;let l=!1;if(n&&!o){if(t&&!Ae(t))for(const a in t)n[a]==null&&$o(r,a,"");for(const a in n)a==="display"&&(l=!0),$o(r,a,n[a])}else if(o){if(t!==n){const a=r[Bf];a&&(n+=";"+a),r.cssText=n,l=jf.test(n)}}else t&&e.removeAttribute("style");al in e&&(e[al]=l?r.display:"",r.display=s)}const il=/\s*!important$/;function $o(e,t,n){if(X(n))n.forEach(r=>$o(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=zf(e,t);il.test(n)?e.setProperty(_n(r),n.replace(il,""),"important"):e[r]=n}}const cl=["Webkit","Moz","ms"],co={};function zf(e,t){const n=co[t];if(n)return n;let r=ze(t);if(r!=="filter"&&r in e)return co[t]=r;r=wn(r);for(let o=0;ouo||(Jf.then(()=>uo=0),uo=Date.now());function Xf(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Xe(Zf(r,n.value),t,5,[r])};return n.value=e,n.attached=Qf(),n}function Zf(e,t){if(X(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>o=>!o._stopped&&r&&r(o))}else return t}const pl=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,ed=(e,t,n,r,o,s,l,a,c)=>{const i=o==="svg";t==="class"?Hf(e,r,i):t==="style"?Vf(e,n,r):Xn(t)?Go(t)||Kf(e,t,n,r,l):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):td(e,t,r,i))?Uf(e,t,r,s,l,a,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Wf(e,t,r,i))};function td(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&pl(t)&&ee(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return pl(t)&&Ae(n)?!1:t in e}const Xa=new WeakMap,Za=new WeakMap,Nr=Symbol("_moveCb"),hl=Symbol("_enterCb"),ei={name:"TransitionGroup",props:we({},Nf,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=Cn(),r=ka();let o,s;return Ia(()=>{if(!o.length)return;const l=e.moveClass||`${e.name||"v"}-move`;if(!ad(o[0].el,n.vnode.el,l))return;o.forEach(od),o.forEach(sd);const a=o.filter(ld);Qa(),a.forEach(c=>{const i=c.el,u=i.style;ht(i,l),u.transform=u.webkitTransform=u.transitionDuration="";const d=i[Nr]=p=>{p&&p.target!==i||(!p||/transform$/.test(p.propertyName))&&(i.removeEventListener("transitionend",d),i[Nr]=null,St(i,l))};i.addEventListener("transitionend",d)})}),()=>{const l=oe(e),a=Ya(l);let c=l.tag||Ge;o=s,s=t.default?is(t.default()):[];for(let i=0;idelete e.mode;ei.props;const rd=ei;function od(e){const t=e.el;t[Nr]&&t[Nr](),t[hl]&&t[hl]()}function sd(e){Za.set(e,e.el.getBoundingClientRect())}function ld(e){const t=Xa.get(e),n=Za.get(e),r=t.left-n.left,o=t.top-n.top;if(r||o){const s=e.el.style;return s.transform=s.webkitTransform=`translate(${r}px,${o}px)`,s.transitionDuration="0s",e}}function ad(e,t,n){const r=e.cloneNode(),o=e[vn];o&&o.forEach(a=>{a.split(/\s+/).forEach(c=>c&&r.classList.remove(c))}),n.split(/\s+/).forEach(a=>a&&r.classList.add(a)),r.style.display="none";const s=t.nodeType===1?t:t.parentNode;s.appendChild(r);const{hasTransform:l}=Ja(r);return s.removeChild(r),l}const id=we({patchProp:ed},$f);let fo,vl=!1;function cd(){return fo=vl?fo:hf(id),vl=!0,fo}const ud=(...e)=>{const t=cd().createApp(...e),{mount:n}=t;return t.mount=r=>{const o=dd(r);if(o)return n(o,!0,fd(o))},t};function fd(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function dd(e){return Ae(e)?document.querySelector(e):e}var pd=["link","meta","script","style","noscript","template"],hd=["title","base"],vd=([e,t,n])=>hd.includes(e)?e:pd.includes(e)?e==="meta"&&t.name?`${e}.${t.name}`:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,Object.entries(t).map(([r,o])=>typeof o=="boolean"?o?[r,""]:null:[r,o]).filter(r=>r!=null).sort(([r],[o])=>r.localeCompare(o)),n]):null,md=e=>{const t=new Set,n=[];return e.forEach(r=>{const o=vd(r);o&&!t.has(o)&&(t.add(o),n.push(r))}),n},gd=e=>e[0]==="/"?e:`/${e}`,ti=e=>e[e.length-1]==="/"||e.endsWith(".html")?e:`${e}/`,Xt=e=>/^(https?:)?\/\//.test(e),bd=/.md((\?|#).*)?$/,mn=(e,t="/")=>!!(Xt(e)||e.startsWith("/")&&!e.startsWith(t)&&!bd.test(e)),ni=e=>/^[a-z][a-z0-9+.-]*:/.test(e),Gr=e=>Object.prototype.toString.call(e)==="[object Object]",yd=e=>{const[t,...n]=e.split(/(\?|#)/);if(!t||t.endsWith("/"))return e;let r=t.replace(/(^|\/)README.md$/i,"$1index.html");return r.endsWith(".md")?r=r.substring(0,r.length-3)+".html":r.endsWith(".html")||(r=r+".html"),r.endsWith("/index.html")&&(r=r.substring(0,r.length-10)),r+n.join("")},ps=e=>e[e.length-1]==="/"?e.slice(0,-1):e,ri=e=>e[0]==="/"?e.slice(1):e,_d=(e,t)=>{const n=Object.keys(e).sort((r,o)=>{const s=o.split("/").length-r.split("/").length;return s!==0?s:o.length-r.length});for(const r of n)if(t.startsWith(r))return r;return"/"},xe=e=>typeof e=="string";const wd="modulepreload",Ed=function(e){return"/"+e},ml={},fe=function(t,n,r){let o=Promise.resolve();if(n&&n.length>0){const s=document.getElementsByTagName("link");o=Promise.all(n.map(l=>{if(l=Ed(l),l in ml)return;ml[l]=!0;const a=l.endsWith(".css"),c=a?'[rel="stylesheet"]':"";if(!!r)for(let d=s.length-1;d>=0;d--){const p=s[d];if(p.href===l&&(!a||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${l}"]${c}`))return;const u=document.createElement("link");if(u.rel=a?"stylesheet":wd,a||(u.as="script",u.crossOrigin=""),u.href=l,document.head.appendChild(u),a)return new Promise((d,p)=>{u.addEventListener("load",d),u.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${l}`)))})}))}return o.then(()=>t()).catch(s=>{const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=s,window.dispatchEvent(l),!l.defaultPrevented)throw s})},Cd=JSON.parse("{}"),xd=Object.fromEntries([["/",{loader:()=>fe(()=>import("./index.html-BSnE9a5s.js"),__vite__mapDeps([0,1])),meta:{y:"h",t:"Home",i:"home"}}],["/faq.html",{loader:()=>fe(()=>import("./faq.html-B9wOlu7B.js"),__vite__mapDeps([2,1])),meta:{y:"a",t:"FAQ"}}],["/intro.html",{loader:()=>fe(()=>import("./intro.html-DJw2Nump.js"),__vite__mapDeps([3,1])),meta:{y:"a",t:""}}],["/community/",{loader:()=>fe(()=>import("./index.html-K9gGP3vT.js"),__vite__mapDeps([4,1])),meta:{y:"a",t:"Community"}}],["/community/editors.html",{loader:()=>fe(()=>import("./editors.html-DwjnlUpI.js"),__vite__mapDeps([5,1])),meta:{y:"a",t:"How to propose fix/change to the website?",O:2}}],["/examples/",{loader:()=>fe(()=>import("./index.html-xbvo-U6r.js"),__vite__mapDeps([6,1])),meta:{y:"a",t:"Use Cases"}}],["/examples/rpc_firewall.html",{loader:()=>fe(()=>import("./rpc_firewall.html-C8sUbYFf.js"),__vite__mapDeps([7,1])),meta:{y:"a",t:"JSON-RPC Firewall"}}],["/examples/web3_rust.html",{loader:()=>fe(()=>import("./web3_rust.html-D5SN0Dc_.js"),__vite__mapDeps([8,1])),meta:{y:"a",t:"Web3 Frontend / Rust Server"}}],["/docs/",{loader:()=>fe(()=>import("./index.html-BbkzL85r.js"),__vite__mapDeps([9,1])),meta:{y:"a",t:"Basic Concept"}}],["/docs/api_rust.html",{loader:()=>fe(()=>import("./api_rust.html-jEWBwXo5.js"),__vite__mapDeps([10,1])),meta:{y:"a",t:""}}],["/docs/api_typescript.html",{loader:()=>fe(()=>import("./api_typescript.html-C6Hyg1mu.js"),__vite__mapDeps([11,1])),meta:{y:"a",t:""}}],["/docs/design.html",{loader:()=>fe(()=>import("./design.html-BzmiLaM4.js"),__vite__mapDeps([12,13,1])),meta:{y:"a",t:"Design"}}],["/docs/future_work.html",{loader:()=>fe(()=>import("./future_work.html-BqJ-TElc.js"),__vite__mapDeps([14,15,1])),meta:{y:"a",t:"Future Work"}}],["/docs/scripts.html",{loader:()=>fe(()=>import("./scripts.html-D_w4s9EQ.js"),__vite__mapDeps([16,1])),meta:{y:"a",t:""}}],["/how-to/full_setup.html",{loader:()=>fe(()=>import("./full_setup.html-CCMysVzO.js"),__vite__mapDeps([17,1])),meta:{y:"a",t:"Rust Development Setup Installation"}}],["/how-to/install.html",{loader:()=>fe(()=>import("./install.html-BizGowkj.js"),__vite__mapDeps([18,1])),meta:{y:"a",t:""}}],["/how-to/npm_only.html",{loader:()=>fe(()=>import("./npm_only.html-Bs9x0lRw.js"),__vite__mapDeps([19,1])),meta:{y:"a",t:""}}],["/how-to/runtime_only.html",{loader:()=>fe(()=>import("./runtime_only.html-BsGx0Xbr.js"),__vite__mapDeps([20,1])),meta:{y:"a",t:""}}],["/ref/",{loader:()=>fe(()=>import("./index.html-2JbiJiHq.js"),__vite__mapDeps([21,1])),meta:{y:"a",t:"Basic Concept"}}],["/ref/api_rust.html",{loader:()=>fe(()=>import("./api_rust.html-BxLNqA0i.js"),__vite__mapDeps([22,1])),meta:{y:"a",t:""}}],["/ref/api_typescript.html",{loader:()=>fe(()=>import("./api_typescript.html-DpDyABcd.js"),__vite__mapDeps([23,1])),meta:{y:"a",t:""}}],["/ref/design.html",{loader:()=>fe(()=>import("./design.html-BCNdCdft.js"),__vite__mapDeps([24,13,1])),meta:{y:"a",t:"Design"}}],["/ref/future_work.html",{loader:()=>fe(()=>import("./future_work.html-iK8jJpLI.js"),__vite__mapDeps([25,15,1])),meta:{y:"a",t:"Future Work"}}],["/ref/scripts.html",{loader:()=>fe(()=>import("./scripts.html-Cae6ml7k.js"),__vite__mapDeps([26,1])),meta:{y:"a",t:""}}],["/404.html",{loader:()=>fe(()=>import("./404.html-B7K0IBbl.js"),__vite__mapDeps([27,1])),meta:{y:"p",t:""}}],["/how-to/",{loader:()=>fe(()=>import("./index.html-By-UCih8.js"),__vite__mapDeps([28,1])),meta:{y:"p",t:"How to"}}]]);/*! + * vue-router v4.2.5 + * (c) 2023 Eduardo San Martin Morote + * @license MIT + */const nn=typeof window<"u";function Sd(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const ce=Object.assign;function po(e,t){const n={};for(const r in t){const o=t[r];n[r]=st(o)?o.map(e):e(o)}return n}const Bn=()=>{},st=Array.isArray,Td=/\/$/,kd=e=>e.replace(Td,"");function ho(e,t,n="/"){let r,o={},s="",l="";const a=t.indexOf("#");let c=t.indexOf("?");return a=0&&(c=-1),c>-1&&(r=t.slice(0,c),s=t.slice(c+1,a>-1?a:t.length),o=e(s)),a>-1&&(r=r||t.slice(0,a),l=t.slice(a,t.length)),r=Id(r??t,n),{fullPath:r+(s&&"?")+s+l,path:r,query:o,hash:l}}function Ad(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function gl(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Ld(e,t,n){const r=t.matched.length-1,o=n.matched.length-1;return r>-1&&r===o&&gn(t.matched[r],n.matched[o])&&oi(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function gn(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function oi(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!Rd(e[n],t[n]))return!1;return!0}function Rd(e,t){return st(e)?bl(e,t):st(t)?bl(t,e):e===t}function bl(e,t){return st(t)?e.length===t.length&&e.every((n,r)=>n===t[r]):e.length===1&&e[0]===t}function Id(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),r=e.split("/"),o=r[r.length-1];(o===".."||o===".")&&r.push("");let s=n.length-1,l,a;for(l=0;l1&&s--;else break;return n.slice(0,s).join("/")+"/"+r.slice(l-(l===r.length?1:0)).join("/")}var Kn;(function(e){e.pop="pop",e.push="push"})(Kn||(Kn={}));var jn;(function(e){e.back="back",e.forward="forward",e.unknown=""})(jn||(jn={}));function Pd(e){if(!e)if(nn){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),kd(e)}const Od=/^[^#]+#/;function Md(e,t){return e.replace(Od,"#")+t}function $d(e,t){const n=document.documentElement.getBoundingClientRect(),r=e.getBoundingClientRect();return{behavior:t.behavior,left:r.left-n.left-(t.left||0),top:r.top-n.top-(t.top||0)}}const Kr=()=>({left:window.pageXOffset,top:window.pageYOffset});function Nd(e){let t;if("el"in e){const n=e.el,r=typeof n=="string"&&n.startsWith("#"),o=typeof n=="string"?r?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=$d(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function yl(e,t){return(history.state?history.state.position-t:-1)+e}const No=new Map;function Dd(e,t){No.set(e,t)}function Fd(e){const t=No.get(e);return No.delete(e),t}let Hd=()=>location.protocol+"//"+location.host;function si(e,t){const{pathname:n,search:r,hash:o}=t,s=e.indexOf("#");if(s>-1){let a=o.includes(e.slice(s))?e.slice(s).length:1,c=o.slice(a);return c[0]!=="/"&&(c="/"+c),gl(c,"")}return gl(n,e)+r+o}function Bd(e,t,n,r){let o=[],s=[],l=null;const a=({state:p})=>{const m=si(e,location),g=n.value,E=t.value;let w=0;if(p){if(n.value=m,t.value=p,l&&l===g){l=null;return}w=E?p.position-E.position:0}else r(m);o.forEach(b=>{b(n.value,g,{delta:w,type:Kn.pop,direction:w?w>0?jn.forward:jn.back:jn.unknown})})};function c(){l=n.value}function i(p){o.push(p);const m=()=>{const g=o.indexOf(p);g>-1&&o.splice(g,1)};return s.push(m),m}function u(){const{history:p}=window;p.state&&p.replaceState(ce({},p.state,{scroll:Kr()}),"")}function d(){for(const p of s)p();s=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",u)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",u,{passive:!0}),{pauseListeners:c,listen:i,destroy:d}}function _l(e,t,n,r=!1,o=!1){return{back:e,current:t,forward:n,replaced:r,position:window.history.length,scroll:o?Kr():null}}function jd(e){const{history:t,location:n}=window,r={value:si(e,n)},o={value:t.state};o.value||s(r.value,{back:null,current:r.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function s(c,i,u){const d=e.indexOf("#"),p=d>-1?(n.host&&document.querySelector("base")?e:e.slice(d))+c:Hd()+e+c;try{t[u?"replaceState":"pushState"](i,"",p),o.value=i}catch(m){console.error(m),n[u?"replace":"assign"](p)}}function l(c,i){const u=ce({},t.state,_l(o.value.back,c,o.value.forward,!0),i,{position:o.value.position});s(c,u,!0),r.value=c}function a(c,i){const u=ce({},o.value,t.state,{forward:c,scroll:Kr()});s(u.current,u,!0);const d=ce({},_l(r.value,c,null),{position:u.position+1},i);s(c,d,!1),r.value=c}return{location:r,state:o,push:a,replace:l}}function Vd(e){e=Pd(e);const t=jd(e),n=Bd(e,t.state,t.location,t.replace);function r(s,l=!0){l||n.pauseListeners(),history.go(s)}const o=ce({location:"",base:e,go:r,createHref:Md.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function zd(e){return typeof e=="string"||e&&typeof e=="object"}function li(e){return typeof e=="string"||typeof e=="symbol"}const vt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},ai=Symbol("");var wl;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(wl||(wl={}));function bn(e,t){return ce(new Error,{type:e,[ai]:!0},t)}function pt(e,t){return e instanceof Error&&ai in e&&(t==null||!!(e.type&t))}const El="[^/]+?",Wd={sensitive:!1,strict:!1,start:!0,end:!0},Ud=/[.+*?^${}()[\]/\\]/g;function qd(e,t){const n=ce({},Wd,t),r=[];let o=n.start?"^":"";const s=[];for(const i of e){const u=i.length?[]:[90];n.strict&&!i.length&&(o+="/");for(let d=0;dt.length?t.length===1&&t[0]===80?1:-1:0}function Kd(e,t){let n=0;const r=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const Yd={type:0,value:""},Jd=/[a-zA-Z0-9_]/;function Qd(e){if(!e)return[[]];if(e==="/")return[[Yd]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(m){throw new Error(`ERR (${n})/"${i}": ${m}`)}let n=0,r=n;const o=[];let s;function l(){s&&o.push(s),s=[]}let a=0,c,i="",u="";function d(){i&&(n===0?s.push({type:0,value:i}):n===1||n===2||n===3?(s.length>1&&(c==="*"||c==="+")&&t(`A repeatable param (${i}) must be alone in its segment. eg: '/:ids+.`),s.push({type:1,value:i,regexp:u,repeatable:c==="*"||c==="+",optional:c==="*"||c==="?"})):t("Invalid state to consume buffer"),i="")}function p(){i+=c}for(;a{l(S)}:Bn}function l(u){if(li(u)){const d=r.get(u);d&&(r.delete(u),n.splice(n.indexOf(d),1),d.children.forEach(l),d.alias.forEach(l))}else{const d=n.indexOf(u);d>-1&&(n.splice(d,1),u.record.name&&r.delete(u.record.name),u.children.forEach(l),u.alias.forEach(l))}}function a(){return n}function c(u){let d=0;for(;d=0&&(u.record.path!==n[d].record.path||!ii(u,n[d]));)d++;n.splice(d,0,u),u.record.name&&!Sl(u)&&r.set(u.record.name,u)}function i(u,d){let p,m={},g,E;if("name"in u&&u.name){if(p=r.get(u.name),!p)throw bn(1,{location:u});E=p.record.name,m=ce(xl(d.params,p.keys.filter(S=>!S.optional).map(S=>S.name)),u.params&&xl(u.params,p.keys.map(S=>S.name))),g=p.stringify(m)}else if("path"in u)g=u.path,p=n.find(S=>S.re.test(g)),p&&(m=p.parse(g),E=p.record.name);else{if(p=d.name?r.get(d.name):n.find(S=>S.re.test(d.path)),!p)throw bn(1,{location:u,currentLocation:d});E=p.record.name,m=ce({},d.params,u.params),g=p.stringify(m)}const w=[];let b=p;for(;b;)w.unshift(b.record),b=b.parent;return{name:E,path:g,params:m,matched:w,meta:np(w)}}return e.forEach(u=>s(u)),{addRoute:s,resolve:i,removeRoute:l,getRoutes:a,getRecordMatcher:o}}function xl(e,t){const n={};for(const r of t)r in e&&(n[r]=e[r]);return n}function ep(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:tp(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function tp(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const r in e.components)t[r]=typeof n=="object"?n[r]:n;return t}function Sl(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function np(e){return e.reduce((t,n)=>ce(t,n.meta),{})}function Tl(e,t){const n={};for(const r in e)n[r]=r in t?t[r]:e[r];return n}function ii(e,t){return t.children.some(n=>n===e||ii(e,n))}const ci=/#/g,rp=/&/g,op=/\//g,sp=/=/g,lp=/\?/g,ui=/\+/g,ap=/%5B/g,ip=/%5D/g,fi=/%5E/g,cp=/%60/g,di=/%7B/g,up=/%7C/g,pi=/%7D/g,fp=/%20/g;function hs(e){return encodeURI(""+e).replace(up,"|").replace(ap,"[").replace(ip,"]")}function dp(e){return hs(e).replace(di,"{").replace(pi,"}").replace(fi,"^")}function Do(e){return hs(e).replace(ui,"%2B").replace(fp,"+").replace(ci,"%23").replace(rp,"%26").replace(cp,"`").replace(di,"{").replace(pi,"}").replace(fi,"^")}function pp(e){return Do(e).replace(sp,"%3D")}function hp(e){return hs(e).replace(ci,"%23").replace(lp,"%3F")}function vp(e){return e==null?"":hp(e).replace(op,"%2F")}function Dr(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function mp(e){const t={};if(e===""||e==="?")return t;const r=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;os&&Do(s)):[r&&Do(r)]).forEach(s=>{s!==void 0&&(t+=(t.length?"&":"")+n,s!=null&&(t+="="+s))})}return t}function gp(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=st(r)?r.map(o=>o==null?null:""+o):r==null?r:""+r)}return t}const bp=Symbol(""),Al=Symbol(""),Yr=Symbol(""),vs=Symbol(""),Fo=Symbol("");function Ln(){let e=[];function t(r){return e.push(r),()=>{const o=e.indexOf(r);o>-1&&e.splice(o,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function Rt(e,t,n,r,o){const s=r&&(r.enterCallbacks[o]=r.enterCallbacks[o]||[]);return()=>new Promise((l,a)=>{const c=d=>{d===!1?a(bn(4,{from:n,to:t})):d instanceof Error?a(d):zd(d)?a(bn(2,{from:t,to:d})):(s&&r.enterCallbacks[o]===s&&typeof d=="function"&&s.push(d),l())},i=e.call(r&&r.instances[o],t,n,c);let u=Promise.resolve(i);e.length<3&&(u=u.then(c)),u.catch(d=>a(d))})}function vo(e,t,n,r){const o=[];for(const s of e)for(const l in s.components){let a=s.components[l];if(!(t!=="beforeRouteEnter"&&!s.instances[l]))if(yp(a)){const i=(a.__vccOpts||a)[t];i&&o.push(Rt(i,n,r,s,l))}else{let c=a();o.push(()=>c.then(i=>{if(!i)return Promise.reject(new Error(`Couldn't resolve component "${l}" at "${s.path}"`));const u=Sd(i)?i.default:i;s.components[l]=u;const p=(u.__vccOpts||u)[t];return p&&Rt(p,n,r,s,l)()}))}}return o}function yp(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Ll(e){const t=Le(Yr),n=Le(vs),r=k(()=>t.resolve(Gt(e.to))),o=k(()=>{const{matched:c}=r.value,{length:i}=c,u=c[i-1],d=n.matched;if(!u||!d.length)return-1;const p=d.findIndex(gn.bind(null,u));if(p>-1)return p;const m=Rl(c[i-2]);return i>1&&Rl(u)===m&&d[d.length-1].path!==m?d.findIndex(gn.bind(null,c[i-2])):p}),s=k(()=>o.value>-1&&Cp(n.params,r.value.params)),l=k(()=>o.value>-1&&o.value===n.matched.length-1&&oi(n.params,r.value.params));function a(c={}){return Ep(c)?t[Gt(e.replace)?"replace":"push"](Gt(e.to)).catch(Bn):Promise.resolve()}return{route:r,href:k(()=>r.value.href),isActive:s,isExactActive:l,navigate:a}}const _p=q({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Ll,setup(e,{slots:t}){const n=Zn(Ll(e)),{options:r}=Le(Yr),o=k(()=>({[Il(e.activeClass,r.linkActiveClass,"router-link-active")]:n.isActive,[Il(e.exactActiveClass,r.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const s=t.default&&t.default(n);return e.custom?s:f("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},s)}}}),wp=_p;function Ep(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Cp(e,t){for(const n in t){const r=t[n],o=e[n];if(typeof r=="string"){if(r!==o)return!1}else if(!st(o)||o.length!==r.length||r.some((s,l)=>s!==o[l]))return!1}return!0}function Rl(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Il=(e,t,n)=>e??t??n,xp=q({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const r=Le(Fo),o=k(()=>e.route||r.value),s=Le(Al,0),l=k(()=>{let i=Gt(s);const{matched:u}=o.value;let d;for(;(d=u[i])&&!d.components;)i++;return i}),a=k(()=>o.value.matched[l.value]);un(Al,k(()=>l.value+1)),un(bp,a),un(Fo,o);const c=te();return ie(()=>[c.value,a.value,e.name],([i,u,d],[p,m,g])=>{u&&(u.instances[d]=i,m&&m!==u&&i&&i===p&&(u.leaveGuards.size||(u.leaveGuards=m.leaveGuards),u.updateGuards.size||(u.updateGuards=m.updateGuards))),i&&u&&(!m||!gn(u,m)||!p)&&(u.enterCallbacks[d]||[]).forEach(E=>E(i))},{flush:"post"}),()=>{const i=o.value,u=e.name,d=a.value,p=d&&d.components[u];if(!p)return Pl(n.default,{Component:p,route:i});const m=d.props[u],g=m?m===!0?i.params:typeof m=="function"?m(i):m:null,w=f(p,ce({},g,t,{onVnodeUnmounted:b=>{b.component.isUnmounted&&(d.instances[u]=null)},ref:c}));return Pl(n.default,{Component:w,route:i})||w}}});function Pl(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const Sp=xp;function Tp(e){const t=Zd(e.routes,e),n=e.parseQuery||mp,r=e.stringifyQuery||kl,o=e.history,s=Ln(),l=Ln(),a=Ln(),c=Fe(vt);let i=vt;nn&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const u=po.bind(null,A=>""+A),d=po.bind(null,vp),p=po.bind(null,Dr);function m(A,V){let B,W;return li(A)?(B=t.getRecordMatcher(A),W=V):W=A,t.addRoute(W,B)}function g(A){const V=t.getRecordMatcher(A);V&&t.removeRoute(V)}function E(){return t.getRoutes().map(A=>A.record)}function w(A){return!!t.getRecordMatcher(A)}function b(A,V){if(V=ce({},V||c.value),typeof A=="string"){const v=ho(n,A,V.path),_=t.resolve({path:v.path},V),L=o.createHref(v.fullPath);return ce(v,_,{params:p(_.params),hash:Dr(v.hash),redirectedFrom:void 0,href:L})}let B;if("path"in A)B=ce({},A,{path:ho(n,A.path,V.path).path});else{const v=ce({},A.params);for(const _ in v)v[_]==null&&delete v[_];B=ce({},A,{params:d(v)}),V.params=d(V.params)}const W=t.resolve(B,V),ae=A.hash||"";W.params=u(p(W.params));const pe=Ad(r,ce({},A,{hash:dp(ae),path:W.path})),h=o.createHref(pe);return ce({fullPath:pe,hash:ae,query:r===kl?gp(A.query):A.query||{}},W,{redirectedFrom:void 0,href:h})}function S(A){return typeof A=="string"?ho(n,A,c.value.path):ce({},A)}function y(A,V){if(i!==A)return bn(8,{from:V,to:A})}function x(A){return M(A)}function $(A){return x(ce(S(A),{replace:!0}))}function C(A){const V=A.matched[A.matched.length-1];if(V&&V.redirect){const{redirect:B}=V;let W=typeof B=="function"?B(A):B;return typeof W=="string"&&(W=W.includes("?")||W.includes("#")?W=S(W):{path:W},W.params={}),ce({query:A.query,hash:A.hash,params:"path"in W?{}:A.params},W)}}function M(A,V){const B=i=b(A),W=c.value,ae=A.state,pe=A.force,h=A.replace===!0,v=C(B);if(v)return M(ce(S(v),{state:typeof v=="object"?ce({},ae,v.state):ae,force:pe,replace:h}),V||B);const _=B;_.redirectedFrom=V;let L;return!pe&&Ld(r,W,B)&&(L=bn(16,{to:_,from:W}),at(W,W,!0,!1)),(L?Promise.resolve(L):F(_,W)).catch(T=>pt(T)?pt(T,2)?T:wt(T):U(T,_,W)).then(T=>{if(T){if(pt(T,2))return M(ce({replace:h},S(T.to),{state:typeof T.to=="object"?ce({},ae,T.to.state):ae,force:pe}),V||_)}else T=H(_,W,!0,h,ae);return Z(_,W,T),T})}function I(A,V){const B=y(A,V);return B?Promise.reject(B):Promise.resolve()}function D(A){const V=en.values().next().value;return V&&typeof V.runWithContext=="function"?V.runWithContext(A):A()}function F(A,V){let B;const[W,ae,pe]=kp(A,V);B=vo(W.reverse(),"beforeRouteLeave",A,V);for(const v of W)v.leaveGuards.forEach(_=>{B.push(Rt(_,A,V))});const h=I.bind(null,A,V);return B.push(h),Oe(B).then(()=>{B=[];for(const v of s.list())B.push(Rt(v,A,V));return B.push(h),Oe(B)}).then(()=>{B=vo(ae,"beforeRouteUpdate",A,V);for(const v of ae)v.updateGuards.forEach(_=>{B.push(Rt(_,A,V))});return B.push(h),Oe(B)}).then(()=>{B=[];for(const v of pe)if(v.beforeEnter)if(st(v.beforeEnter))for(const _ of v.beforeEnter)B.push(Rt(_,A,V));else B.push(Rt(v.beforeEnter,A,V));return B.push(h),Oe(B)}).then(()=>(A.matched.forEach(v=>v.enterCallbacks={}),B=vo(pe,"beforeRouteEnter",A,V),B.push(h),Oe(B))).then(()=>{B=[];for(const v of l.list())B.push(Rt(v,A,V));return B.push(h),Oe(B)}).catch(v=>pt(v,8)?v:Promise.reject(v))}function Z(A,V,B){a.list().forEach(W=>D(()=>W(A,V,B)))}function H(A,V,B,W,ae){const pe=y(A,V);if(pe)return pe;const h=V===vt,v=nn?history.state:{};B&&(W||h?o.replace(A.fullPath,ce({scroll:h&&v&&v.scroll},ae)):o.push(A.fullPath,ae)),c.value=A,at(A,V,B,h),wt()}let J;function be(){J||(J=o.listen((A,V,B)=>{if(!fr.listening)return;const W=b(A),ae=C(W);if(ae){M(ce(ae,{replace:!0}),W).catch(Bn);return}i=W;const pe=c.value;nn&&Dd(yl(pe.fullPath,B.delta),Kr()),F(W,pe).catch(h=>pt(h,12)?h:pt(h,2)?(M(h.to,W).then(v=>{pt(v,20)&&!B.delta&&B.type===Kn.pop&&o.go(-1,!1)}).catch(Bn),Promise.reject()):(B.delta&&o.go(-B.delta,!1),U(h,W,pe))).then(h=>{h=h||H(W,pe,!1),h&&(B.delta&&!pt(h,8)?o.go(-B.delta,!1):B.type===Kn.pop&&pt(h,20)&&o.go(-1,!1)),Z(W,pe,h)}).catch(Bn)}))}let ye=Ln(),G=Ln(),ne;function U(A,V,B){wt(A);const W=G.list();return W.length?W.forEach(ae=>ae(A,V,B)):console.error(A),Promise.reject(A)}function Ze(){return ne&&c.value!==vt?Promise.resolve():new Promise((A,V)=>{ye.add([A,V])})}function wt(A){return ne||(ne=!A,be(),ye.list().forEach(([V,B])=>A?B(A):V()),ye.reset()),A}function at(A,V,B,W){const{scrollBehavior:ae}=e;if(!nn||!ae)return Promise.resolve();const pe=!B&&Fd(yl(A.fullPath,0))||(W||!B)&&history.state&&history.state.scroll||null;return Qt().then(()=>ae(A,V,pe)).then(h=>h&&Nd(h)).catch(h=>U(h,A,V))}const He=A=>o.go(A);let Zt;const en=new Set,fr={currentRoute:c,listening:!0,addRoute:m,removeRoute:g,hasRoute:w,getRoutes:E,resolve:b,options:e,push:x,replace:$,go:He,back:()=>He(-1),forward:()=>He(1),beforeEach:s.add,beforeResolve:l.add,afterEach:a.add,onError:G.add,isReady:Ze,install(A){const V=this;A.component("RouterLink",wp),A.component("RouterView",Sp),A.config.globalProperties.$router=V,Object.defineProperty(A.config.globalProperties,"$route",{enumerable:!0,get:()=>Gt(c)}),nn&&!Zt&&c.value===vt&&(Zt=!0,x(o.location).catch(ae=>{}));const B={};for(const ae in vt)Object.defineProperty(B,ae,{get:()=>c.value[ae],enumerable:!0});A.provide(Yr,V),A.provide(vs,fa(B)),A.provide(Fo,c);const W=A.unmount;en.add(A),A.unmount=function(){en.delete(A),en.size<1&&(i=vt,J&&J(),J=null,c.value=vt,Zt=!1,ne=!1),W()}}};function Oe(A){return A.reduce((V,B)=>V.then(()=>D(B)),Promise.resolve())}return fr}function kp(e,t){const n=[],r=[],o=[],s=Math.max(t.matched.length,e.matched.length);for(let l=0;lgn(i,a))?r.push(a):n.push(a));const c=e.matched[l];c&&(t.matched.find(i=>gn(i,c))||o.push(c))}return[n,r,o]}function Dt(){return Le(Yr)}function _t(){return Le(vs)}var ms=Symbol(""),dt=()=>{const e=Le(ms);if(!e)throw new Error("useClientData() is called without provider.");return e},Ap=()=>dt().pageComponent,ge=()=>dt().pageData,Se=()=>dt().pageFrontmatter,Lp=()=>dt().pageHead,hi=()=>dt().pageLang,Rp=()=>dt().pageLayout,xn=()=>dt().routeLocale,Ip=()=>dt().routes,vi=()=>dt().siteData,gs=()=>dt().siteLocaleData,Pp=Symbol(""),mi=Fe(Cd),Yn=Fe(xd),gi=e=>{const t=yd(e);if(Yn.value[t])return t;const n=encodeURI(t);return Yn.value[n]?n:mi.value[t]||t},Jr=e=>{const t=gi(e),n=Yn.value[t]??{...Yn.value["/404.html"],notFound:!0};return{path:t,notFound:!1,...n}},Qr=q({name:"ClientOnly",setup(e,t){const n=te(!1);return _e(()=>{n.value=!0}),()=>{var r,o;return n.value?(o=(r=t.slots).default)==null?void 0:o.call(r):null}}}),bi=q({name:"Content",props:{path:{type:String,required:!1,default:""}},setup(e){const t=Ap(),n=k(()=>{if(!e.path)return t.value;const r=Jr(e.path);return ju(()=>r.loader().then(({comp:o})=>o))});return()=>f(n.value)}}),Ne=e=>Xt(e)?e:`/${ri(e)}`,Op=e=>{if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget){const t=e.currentTarget.getAttribute("target");if(t!=null&&t.match(/\b_blank\b/i))return}return e.preventDefault(),!0}},je=({active:e=!1,activeClass:t="route-link-active",to:n,...r},{slots:o})=>{var a;const s=Dt(),l=Ne(gi(n));return f("a",{...r,class:["route-link",{[t]:e}],href:l,onClick:(c={})=>{Op(c)?s.push(n).catch():Promise.resolve()}},(a=o.default)==null?void 0:a.call(o))};je.displayName="RouteLink";je.props={active:Boolean,activeClass:String,to:String};var Mp="Layout",$p="en-US",jt=Zn({resolveLayouts:e=>e.reduce((t,n)=>({...t,...n.layouts}),{}),resolvePageHead:(e,t,n)=>{const r=xe(t.description)?t.description:n.description,o=[...Array.isArray(t.head)?t.head:[],...n.head,["title",{},e],["meta",{name:"description",content:r}]];return md(o)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(n=>!!n).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||$p,resolvePageLayout:(e,t)=>{const n=xe(e.frontmatter.layout)?e.frontmatter.layout:Mp;return t[n]},resolveRouteLocale:(e,t)=>_d(e,t),resolveSiteLocaleData:(e,t)=>{var n;return{...e,...e.locales[t],head:[...((n=e.locales[t])==null?void 0:n.head)??[],...e.head??[]]}}});const Np={};var lt=(e={})=>e;const sr=e=>{const t=xn();return k(()=>e[t.value]??{})},Dp=(e,t)=>{var r;const n=(r=(t==null?void 0:t._instance)||Cn())==null?void 0:r.appContext.components;return n?e in n||ze(e)in n||wn(ze(e))in n:!1},Fp=e=>typeof e<"u",mo=e=>typeof e=="number",Ho=Array.isArray,Jn=(e,t)=>xe(e)&&e.startsWith(t),Hp=(e,t)=>xe(e)&&e.endsWith(t),bs=Object.entries,Bp=Object.fromEntries,lr=Object.keys,jp=e=>{if(e){if(typeof e=="number")return new Date(e);const t=Date.parse(e.toString());if(!Number.isNaN(t))return new Date(t)}return null},ys=e=>Jn(e,"/"),Ee=({name:e="",color:t="currentColor"},{slots:n})=>{var r;return f("svg",{xmlns:"http://www.w3.org/2000/svg",class:["icon",`${e}-icon`],viewBox:"0 0 1024 1024",fill:t,"aria-label":`${e} icon`},(r=n.default)==null?void 0:r.call(n))};Ee.displayName="IconBase";const yi=(e,{slots:t})=>{var n;return(n=t.default)==null?void 0:n.call(t)},_i=()=>f(Ee,{name:"github"},()=>f("path",{d:"M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"}));_i.displayName="GitHubIcon";const wi=()=>f(Ee,{name:"gitlab"},()=>f("path",{d:"M229.333 78.688C223.52 62 199.895 62 193.895 78.688L87.958 406.438h247.5c-.188 0-106.125-327.75-106.125-327.75zM33.77 571.438c-4.875 15 .563 31.687 13.313 41.25l464.812 345L87.77 406.438zm301.5-165 176.813 551.25 176.812-551.25zm655.125 165-54-165-424.312 551.25 464.812-345c12.938-9.563 18.188-26.25 13.5-41.25zM830.27 78.688c-5.812-16.688-29.437-16.688-35.437 0l-106.125 327.75h247.5z"}));wi.displayName="GitLabIcon";const Ei=()=>f(Ee,{name:"gitee"},()=>f("path",{d:"M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm242.97-533.34H482.39a23.7 23.7 0 0 0-23.7 23.7l-.03 59.28c0 13.08 10.59 23.7 23.7 23.7h165.96a23.7 23.7 0 0 1 23.7 23.7v11.85a71.1 71.1 0 0 1-71.1 71.1H375.71a23.7 23.7 0 0 1-23.7-23.7V423.11a71.1 71.1 0 0 1 71.1-71.1h331.8a23.7 23.7 0 0 0 23.7-23.7l.06-59.25a23.73 23.73 0 0 0-23.7-23.73H423.11a177.78 177.78 0 0 0-177.78 177.75v331.83c0 13.08 10.62 23.7 23.7 23.7h349.62a159.99 159.99 0 0 0 159.99-159.99V482.33a23.7 23.7 0 0 0-23.7-23.7z"}));Ei.displayName="GiteeIcon";const Ci=()=>f(Ee,{name:"bitbucket"},()=>f("path",{d:"M575.256 490.862c6.29 47.981-52.005 85.723-92.563 61.147-45.714-20.004-45.714-92.562-1.133-113.152 38.29-23.442 93.696 7.424 93.696 52.005zm63.451-11.996c-10.276-81.152-102.29-134.839-177.152-101.156-47.433 21.138-79.433 71.424-77.129 124.562 2.853 69.705 69.157 126.866 138.862 120.576S647.3 548.571 638.708 478.83zm136.558-309.723c-25.161-33.134-67.986-38.839-105.728-45.13-106.862-17.151-216.576-17.7-323.438 1.134-35.438 5.706-75.447 11.996-97.719 43.996 36.572 34.304 88.576 39.424 135.424 45.129 84.553 10.862 171.447 11.447 256 .585 47.433-5.705 99.987-10.276 135.424-45.714zm32.585 591.433c-16.018 55.99-6.839 131.438-66.304 163.986-102.29 56.576-226.304 62.867-338.87 42.862-59.43-10.862-129.135-29.696-161.72-85.723-14.3-54.858-23.442-110.848-32.585-166.84l3.438-9.142 10.276-5.157c170.277 112.567 408.576 112.567 579.438 0 26.844 8.01 6.84 40.558 6.29 60.014zm103.424-549.157c-19.42 125.148-41.728 249.71-63.415 374.272-6.29 36.572-41.728 57.162-71.424 72.558-106.862 53.724-231.424 62.866-348.562 50.286-79.433-8.558-160.585-29.696-225.134-79.433-30.28-23.443-30.28-63.415-35.986-97.134-20.005-117.138-42.862-234.277-57.161-352.585 6.839-51.42 64.585-73.728 107.447-89.71 57.16-21.138 118.272-30.866 178.87-36.571 129.134-12.58 261.157-8.01 386.304 28.562 44.581 13.13 92.563 31.415 122.844 69.705 13.714 17.7 9.143 40.01 6.29 60.014z"}));Ci.displayName="BitbucketIcon";const xi=()=>f(Ee,{name:"source"},()=>f("path",{d:"M601.92 475.2c0 76.428-8.91 83.754-28.512 99.594-14.652 11.88-43.956 14.058-78.012 16.434-18.81 1.386-40.392 2.97-62.172 6.534-18.612 2.97-36.432 9.306-53.064 17.424V299.772c37.818-21.978 63.36-62.766 63.36-109.692 0-69.894-56.826-126.72-126.72-126.72S190.08 120.186 190.08 190.08c0 46.926 25.542 87.714 63.36 109.692v414.216c-37.818 21.978-63.36 62.766-63.36 109.692 0 69.894 56.826 126.72 126.72 126.72s126.72-56.826 126.72-126.72c0-31.086-11.286-59.598-29.7-81.576 13.266-9.504 27.522-17.226 39.996-19.206 16.038-2.574 32.868-3.762 50.688-5.148 48.312-3.366 103.158-7.326 148.896-44.55 61.182-49.698 74.25-103.158 75.24-187.902V475.2h-126.72zM316.8 126.72c34.848 0 63.36 28.512 63.36 63.36s-28.512 63.36-63.36 63.36-63.36-28.512-63.36-63.36 28.512-63.36 63.36-63.36zm0 760.32c-34.848 0-63.36-28.512-63.36-63.36s28.512-63.36 63.36-63.36 63.36 28.512 63.36 63.36-28.512 63.36-63.36 63.36zM823.68 158.4h-95.04V63.36h-126.72v95.04h-95.04v126.72h95.04v95.04h126.72v-95.04h95.04z"}));xi.displayName="SourceIcon";const ot=(e,t)=>{var r;const n=(r=(t==null?void 0:t._instance)||Cn())==null?void 0:r.appContext.components;return n?e in n||ze(e)in n||wn(ze(e))in n:!1},Si=(e,t)=>{let n=1;for(let r=0;r>6;return n+=n<<3,n^=n>>11,n%t},Ti=/#.*$/u,Vp=e=>{const t=Ti.exec(e);return t?t[0]:""},Ol=e=>decodeURI(e).replace(Ti,"").replace(/\/index\.html$/iu,"/").replace(/\.html$/iu,"").replace(/(README|index)?\.md$/iu,""),ki=(e,t)=>{if(!Fp(t))return!1;const n=Ol(e.path),r=Ol(t),o=Vp(t);return o?o===e.hash&&(!r||n===r):n===r},zp=e=>Xt(e)?e:`https://github.com/${e}`,Ai=e=>!Xt(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null;var Wp=e=>Object.prototype.toString.call(e)==="[object Object]",Qn=e=>typeof e=="string";const Li=Array.isArray,Ml=e=>Wp(e)&&Qn(e.name),$l=(e,t=!1)=>e?Li(e)?e.map(n=>Qn(n)?{name:n}:Ml(n)?n:null).filter(n=>n!==null):Qn(e)?[{name:e}]:Ml(e)?[e]:(console.error(`Expect "author" to be \`AuthorInfo[] | AuthorInfo | string[] | string ${t?"":"| false"} | undefined\`, but got`,e),[]):[],Ri=(e,t)=>{if(e){if(Li(e)&&e.every(Qn))return e;if(Qn(e))return[e];console.error(`Expect ${t||"value"} to be \`string[] | string | undefined\`, but got`,e)}return[]},Up=e=>Ri(e,"category"),qp=e=>Ri(e,"tag");function _s(e,t){let n,r,o;const s=te(!0),l=()=>{s.value=!0,o()};ie(e,l,{flush:"sync"});const a=typeof t=="function"?t:t.get,c=typeof t=="function"?void 0:t.set,i=ga((u,d)=>(r=u,o=d,{get(){return s.value&&(n=a(),s.value=!1),r(),n},set(p){c==null||c(p)}}));return Object.isExtensible(i)&&(i.trigger=l),i}function Sn(e){return Zl()?(Kc(e),!0):!1}function Re(e){return typeof e=="function"?e():Gt(e)}const ar=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Gp=Object.prototype.toString,Kp=e=>Gp.call(e)==="[object Object]",Kt=()=>{},Nl=Yp();function Yp(){var e,t;return ar&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function ws(e,t){function n(...r){return new Promise((o,s)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(o).catch(s)})}return n}const Ii=e=>e();function Jp(e,t={}){let n,r,o=Kt;const s=a=>{clearTimeout(a),o(),o=Kt};return a=>{const c=Re(e),i=Re(t.maxWait);return n&&s(n),c<=0||i!==void 0&&i<=0?(r&&(s(r),r=null),Promise.resolve(a())):new Promise((u,d)=>{o=t.rejectOnCancel?d:u,i&&!r&&(r=setTimeout(()=>{n&&s(n),r=null,u(a())},i)),n=setTimeout(()=>{r&&s(r),r=null,u(a())},c)})}}function Qp(e,t=!0,n=!0,r=!1){let o=0,s,l=!0,a=Kt,c;const i=()=>{s&&(clearTimeout(s),s=void 0,a(),a=Kt)};return d=>{const p=Re(e),m=Date.now()-o,g=()=>c=d();return i(),p<=0?(o=Date.now(),g()):(m>p&&(n||!l)?(o=Date.now(),g()):t&&(c=new Promise((E,w)=>{a=r?w:E,s=setTimeout(()=>{o=Date.now(),l=!0,E(g()),i()},Math.max(0,p-m))})),!n&&!s&&(s=setTimeout(()=>l=!0,p)),l=!1,c)}}function Xp(e=Ii){const t=te(!0);function n(){t.value=!1}function r(){t.value=!0}const o=(...s)=>{t.value&&e(...s)};return{isActive:er(t),pause:n,resume:r,eventFilter:o}}function Zp(e){let t;function n(){return t||(t=e()),t}return n.reset=async()=>{const r=t;t=void 0,r&&await r},n}function Pi(e){return e||Cn()}function eh(...e){if(e.length!==1)return Vr(...e);const t=e[0];return typeof t=="function"?er(ga(()=>({get:t,set:Kt}))):te(t)}function th(e,t=200,n={}){return ws(Jp(t,n),e)}function nh(e,t=200,n=!1,r=!0,o=!1){return ws(Qp(t,n,r,o),e)}function rh(e,t,n={}){const{eventFilter:r=Ii,...o}=n;return ie(e,ws(r,t),o)}function oh(e,t,n={}){const{eventFilter:r,...o}=n,{eventFilter:s,pause:l,resume:a,isActive:c}=Xp(r);return{stop:rh(e,t,{...o,eventFilter:s}),pause:l,resume:a,isActive:c}}function Xr(e,t=!0,n){Pi()?_e(e,n):t?e():Qt(e)}function sh(e,t){Pi(t)&&En(e,t)}function lh(e,t,n={}){const{immediate:r=!0}=n,o=te(!1);let s=null;function l(){s&&(clearTimeout(s),s=null)}function a(){o.value=!1,l()}function c(...i){l(),o.value=!0,s=setTimeout(()=>{o.value=!1,s=null,e(...i)},Re(t))}return r&&(o.value=!0,ar&&c()),Sn(a),{isPending:er(o),start:c,stop:a}}function Dl(e=!1,t={}){const{truthyValue:n=!0,falsyValue:r=!1}=t,o=Ie(e),s=te(e);function l(a){if(arguments.length)return s.value=a,s.value;{const c=Re(n);return s.value=s.value===c?Re(r):c,s.value}}return o?l:[s,l]}function gt(e){var t;const n=Re(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Nt=ar?window:void 0,Oi=ar?window.document:void 0,Mi=ar?window.navigator:void 0;function Pe(...e){let t,n,r,o;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,o]=e,t=Nt):[t,n,r,o]=e,!t)return Kt;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const s=[],l=()=>{s.forEach(u=>u()),s.length=0},a=(u,d,p,m)=>(u.addEventListener(d,p,m),()=>u.removeEventListener(d,p,m)),c=ie(()=>[gt(t),Re(o)],([u,d])=>{if(l(),!u)return;const p=Kp(d)?{...d}:d;s.push(...n.flatMap(m=>r.map(g=>a(u,m,g,p))))},{immediate:!0,flush:"post"}),i=()=>{c(),l()};return Sn(i),i}function ah(){const e=te(!1);return Cn()&&_e(()=>{e.value=!0}),e}function ir(e){const t=ah();return k(()=>(t.value,!!e()))}function $i(e,t={}){const{window:n=Nt}=t,r=ir(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let o;const s=te(!1),l=i=>{s.value=i.matches},a=()=>{o&&("removeEventListener"in o?o.removeEventListener("change",l):o.removeListener(l))},c=Sa(()=>{r.value&&(a(),o=n.matchMedia(Re(e)),"addEventListener"in o?o.addEventListener("change",l):o.addListener(l),s.value=o.matches)});return Sn(()=>{c(),a(),o=void 0}),s}function Fl(e,t={}){const{controls:n=!1,navigator:r=Mi}=t,o=ir(()=>r&&"permissions"in r);let s;const l=typeof e=="string"?{name:e}:e,a=te(),c=()=>{s&&(a.value=s.state)},i=Zp(async()=>{if(o.value){if(!s)try{s=await r.permissions.query(l),Pe(s,"change",c),c()}catch{a.value="prompt"}return s}});return i(),n?{state:a,isSupported:o,query:i}:a}function ih(e={}){const{navigator:t=Mi,read:n=!1,source:r,copiedDuring:o=1500,legacy:s=!1}=e,l=ir(()=>t&&"clipboard"in t),a=Fl("clipboard-read"),c=Fl("clipboard-write"),i=k(()=>l.value||s),u=te(""),d=te(!1),p=lh(()=>d.value=!1,o);function m(){l.value&&a.value!=="denied"?t.clipboard.readText().then(b=>{u.value=b}):u.value=w()}i.value&&n&&Pe(["copy","cut"],m);async function g(b=Re(r)){i.value&&b!=null&&(l.value&&c.value!=="denied"?await t.clipboard.writeText(b):E(b),u.value=b,d.value=!0,p.start())}function E(b){const S=document.createElement("textarea");S.value=b??"",S.style.position="absolute",S.style.opacity="0",document.body.appendChild(S),S.select(),document.execCommand("copy"),S.remove()}function w(){var b,S,y;return(y=(S=(b=document==null?void 0:document.getSelection)==null?void 0:b.call(document))==null?void 0:S.toString())!=null?y:""}return{isSupported:i,text:u,copied:d,copy:g}}const wr=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Er="__vueuse_ssr_handlers__",ch=uh();function uh(){return Er in wr||(wr[Er]=wr[Er]||{}),wr[Er]}function fh(e,t){return ch[e]||t}function dh(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const ph={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Hl="vueuse-storage";function Es(e,t,n,r={}){var o;const{flush:s="pre",deep:l=!0,listenToStorageChanges:a=!0,writeDefaults:c=!0,mergeDefaults:i=!1,shallow:u,window:d=Nt,eventFilter:p,onError:m=D=>{console.error(D)},initOnMounted:g}=r,E=(u?Fe:te)(typeof t=="function"?t():t);if(!n)try{n=fh("getDefaultStorage",()=>{var D;return(D=Nt)==null?void 0:D.localStorage})()}catch(D){m(D)}if(!n)return E;const w=Re(t),b=dh(w),S=(o=r.serializer)!=null?o:ph[b],{pause:y,resume:x}=oh(E,()=>$(E.value),{flush:s,deep:l,eventFilter:p});return d&&a&&Xr(()=>{Pe(d,"storage",I),Pe(d,Hl,M),g&&I()}),g||I(),E;function $(D){try{if(D==null)n.removeItem(e);else{const F=S.write(D),Z=n.getItem(e);Z!==F&&(n.setItem(e,F),d&&d.dispatchEvent(new CustomEvent(Hl,{detail:{key:e,oldValue:Z,newValue:F,storageArea:n}})))}}catch(F){m(F)}}function C(D){const F=D?D.newValue:n.getItem(e);if(F==null)return c&&w!=null&&n.setItem(e,S.write(w)),w;if(!D&&i){const Z=S.read(F);return typeof i=="function"?i(Z,w):b==="object"&&!Array.isArray(Z)?{...w,...Z}:Z}else return typeof F!="string"?F:S.read(F)}function M(D){I(D.detail)}function I(D){if(!(D&&D.storageArea!==n)){if(D&&D.key==null){E.value=w;return}if(!(D&&D.key!==e)){y();try{(D==null?void 0:D.newValue)!==S.write(E.value)&&(E.value=C(D))}catch(F){m(F)}finally{D?Qt(x):x()}}}}}function hh(e){return $i("(prefers-color-scheme: dark)",e)}function vh(e,t,n={}){const{window:r=Nt,...o}=n;let s;const l=ir(()=>r&&"ResizeObserver"in r),a=()=>{s&&(s.disconnect(),s=void 0)},c=k(()=>Array.isArray(e)?e.map(d=>gt(d)):[gt(e)]),i=ie(c,d=>{if(a(),l.value&&r){s=new ResizeObserver(t);for(const p of d)p&&s.observe(p,o)}},{immediate:!0,flush:"post",deep:!0}),u=()=>{a(),i()};return Sn(u),{isSupported:l,stop:u}}function mh(e,t={width:0,height:0},n={}){const{window:r=Nt,box:o="content-box"}=n,s=k(()=>{var d,p;return(p=(d=gt(e))==null?void 0:d.namespaceURI)==null?void 0:p.includes("svg")}),l=te(t.width),a=te(t.height),{stop:c}=vh(e,([d])=>{const p=o==="border-box"?d.borderBoxSize:o==="content-box"?d.contentBoxSize:d.devicePixelContentBoxSize;if(r&&s.value){const m=gt(e);if(m){const g=r.getComputedStyle(m);l.value=Number.parseFloat(g.width),a.value=Number.parseFloat(g.height)}}else if(p){const m=Array.isArray(p)?p:[p];l.value=m.reduce((g,{inlineSize:E})=>g+E,0),a.value=m.reduce((g,{blockSize:E})=>g+E,0)}else l.value=d.contentRect.width,a.value=d.contentRect.height},n);Xr(()=>{const d=gt(e);d&&(l.value="offsetWidth"in d?d.offsetWidth:t.width,a.value="offsetHeight"in d?d.offsetHeight:t.height)});const i=ie(()=>gt(e),d=>{l.value=d?t.width:0,a.value=d?t.height:0});function u(){c(),i()}return{width:l,height:a,stop:u}}const Bl=["fullscreenchange","webkitfullscreenchange","webkitendfullscreen","mozfullscreenchange","MSFullscreenChange"];function Cs(e,t={}){const{document:n=Oi,autoExit:r=!1}=t,o=k(()=>{var b;return(b=gt(e))!=null?b:n==null?void 0:n.querySelector("html")}),s=te(!1),l=k(()=>["requestFullscreen","webkitRequestFullscreen","webkitEnterFullscreen","webkitEnterFullScreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen"].find(b=>n&&b in n||o.value&&b in o.value)),a=k(()=>["exitFullscreen","webkitExitFullscreen","webkitExitFullScreen","webkitCancelFullScreen","mozCancelFullScreen","msExitFullscreen"].find(b=>n&&b in n||o.value&&b in o.value)),c=k(()=>["fullScreen","webkitIsFullScreen","webkitDisplayingFullscreen","mozFullScreen","msFullscreenElement"].find(b=>n&&b in n||o.value&&b in o.value)),i=["fullscreenElement","webkitFullscreenElement","mozFullScreenElement","msFullscreenElement"].find(b=>n&&b in n),u=ir(()=>o.value&&n&&l.value!==void 0&&a.value!==void 0&&c.value!==void 0),d=()=>i?(n==null?void 0:n[i])===o.value:!1,p=()=>{if(c.value){if(n&&n[c.value]!=null)return n[c.value];{const b=o.value;if((b==null?void 0:b[c.value])!=null)return!!b[c.value]}}return!1};async function m(){if(!(!u.value||!s.value)){if(a.value)if((n==null?void 0:n[a.value])!=null)await n[a.value]();else{const b=o.value;(b==null?void 0:b[a.value])!=null&&await b[a.value]()}s.value=!1}}async function g(){if(!u.value||s.value)return;p()&&await m();const b=o.value;l.value&&(b==null?void 0:b[l.value])!=null&&(await b[l.value](),s.value=!0)}async function E(){await(s.value?m():g())}const w=()=>{const b=p();(!b||b&&d())&&(s.value=b)};return Pe(n,Bl,w,!1),Pe(()=>gt(o),Bl,w,!1),r&&Sn(m),{isSupported:u,isFullscreen:s,enter:g,exit:m,toggle:E}}function go(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function bo(e,t=Kt,n={}){const{immediate:r=!0,manual:o=!1,type:s="text/javascript",async:l=!0,crossOrigin:a,referrerPolicy:c,noModule:i,defer:u,document:d=Oi,attrs:p={}}=n,m=te(null);let g=null;const E=S=>new Promise((y,x)=>{const $=I=>(m.value=I,y(I),I);if(!d){y(!1);return}let C=!1,M=d.querySelector(`script[src="${Re(e)}"]`);M?M.hasAttribute("data-loaded")&&$(M):(M=d.createElement("script"),M.type=s,M.async=l,M.src=Re(e),u&&(M.defer=u),a&&(M.crossOrigin=a),i&&(M.noModule=i),c&&(M.referrerPolicy=c),Object.entries(p).forEach(([I,D])=>M==null?void 0:M.setAttribute(I,D)),C=!0),M.addEventListener("error",I=>x(I)),M.addEventListener("abort",I=>x(I)),M.addEventListener("load",()=>{M.setAttribute("data-loaded","true"),t(M),$(M)}),C&&(M=d.head.appendChild(M)),S||$(M)}),w=(S=!0)=>(g||(g=E(S)),g),b=()=>{if(!d)return;g=null,m.value&&(m.value=null);const S=d.querySelector(`script[src="${Re(e)}"]`);S&&d.head.removeChild(S)};return r&&!o&&Xr(w),o||sh(b),{scriptTag:m,load:w,unload:b}}function Ni(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const Cr=new WeakMap;function Di(e,t=!1){const n=te(t);let r=null,o;ie(eh(e),a=>{const c=go(Re(a));if(c){const i=c;Cr.get(i)||Cr.set(i,o),n.value&&(i.style.overflow="hidden")}},{immediate:!0});const s=()=>{const a=go(Re(e));!a||n.value||(Nl&&(r=Pe(a,"touchmove",c=>{gh(c)},{passive:!1})),a.style.overflow="hidden",n.value=!0)},l=()=>{var a;const c=go(Re(e));!c||!n.value||(Nl&&(r==null||r()),c.style.overflow=(a=Cr.get(c))!=null?a:"",Cr.delete(c),n.value=!1)};return Sn(l),k({get(){return n.value},set(a){a?s():l()}})}function bh(e={}){const{window:t=Nt,behavior:n="auto"}=e;if(!t)return{x:te(0),y:te(0)};const r=te(t.scrollX),o=te(t.scrollY),s=k({get(){return r.value},set(a){scrollTo({left:a,behavior:n})}}),l=k({get(){return o.value},set(a){scrollTo({top:a,behavior:n})}});return Pe(t,"scroll",()=>{r.value=t.scrollX,o.value=t.scrollY},{capture:!1,passive:!0}),{x:s,y:l}}function yh(e={}){const{window:t=Nt,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:r=Number.POSITIVE_INFINITY,listenOrientation:o=!0,includeScrollbar:s=!0}=e,l=te(n),a=te(r),c=()=>{t&&(s?(l.value=t.innerWidth,a.value=t.innerHeight):(l.value=t.document.documentElement.clientWidth,a.value=t.document.documentElement.clientHeight))};if(c(),Xr(c),Pe("resize",c,{passive:!0}),o){const i=$i("(orientation: portrait)");ie(i,()=>c())}return{width:l,height:a}}var _h=q({name:"FontIcon",props:{icon:{type:String,default:""},color:{type:String,default:""},size:{type:[String,Number],default:""}},setup(e){const t=k(()=>{const r=["font-icon icon"],o=`fas fa-${e.icon}`;return r.push("fa-fw fa-sm"),r.push(e.icon.includes(" ")?e.icon:o),r}),n=k(()=>{const r={};return e.color&&(r.color=e.color),e.size&&(r["font-size"]=Number.isNaN(Number(e.size))?e.size:`${e.size}px`),lr(r).length?r:null});return()=>e.icon?f("span",{key:e.icon,class:t.value,style:n.value}):null}});const Fi=({type:e="info",text:t="",vertical:n,color:r},{slots:o})=>{var s;return f("span",{class:["vp-badge",e,{diy:r}],style:{verticalAlign:n??!1,backgroundColor:r??!1}},((s=o.default)==null?void 0:s.call(o))||t)};Fi.displayName="Badge";const Hi=({title:e,desc:t="",logo:n,background:r,color:o,link:s})=>{const l=[n?f("img",{class:"vp-card-logo",src:Ne(n),loading:"lazy","no-view":""}):null,f("div",{class:"vp-card-content"},[f("div",{class:"vp-card-title",innerHTML:e}),f("hr"),f("div",{class:"vp-card-desc",innerHTML:t})])],a={};return r&&(a.background=r),o&&(a.color=o),s?mn(s)?f("a",{class:"vp-card",href:s,target:"_blank",style:a},l):f(je,{to:s,class:"vp-card",style:a},()=>l):f("div",{class:"vp-card",style:a},l)};Hi.displayName="VPCard";const wh=lt({enhance:({app:e})=>{ot("FontIcon")||e.component("FontIcon",_h),ot("Badge")||e.component("Badge",Fi),ot("VPCard")||e.component("VPCard",Hi)},setup:()=>{bo("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/js/brands.min.js",()=>{},{attrs:{"data-auto-replace-svg":"nest"}}),bo("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/js/solid.min.js",()=>{},{attrs:{"data-auto-replace-svg":"nest"}}),bo("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/js/fontawesome.min.js",()=>{},{attrs:{"data-auto-replace-svg":"nest"}})},rootComponents:[]}),jl=async(e,t)=>{const{path:n,query:r}=e.currentRoute.value,{scrollBehavior:o}=e.options;e.options.scrollBehavior=void 0,await e.replace({path:n,query:r,hash:t}),e.options.scrollBehavior=o},Eh=({headerLinkSelector:e,headerAnchorSelector:t,delay:n,offset:r=5})=>{const o=Dt();Pe("scroll",th(()=>{var g,E;const l=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(l-0)d.some(b=>b.hash===w.hash));for(let w=0;w=(((g=b.parentElement)==null?void 0:g.offsetTop)??0)-r,x=!S||l<(((E=S.parentElement)==null?void 0:E.offsetTop)??0)-r;if(!(y&&x))continue;const C=decodeURIComponent(o.currentRoute.value.hash),M=decodeURIComponent(b.hash);if(C===M)return;if(u){for(let I=w+1;Ixe(e.title)?{title:e.title}:null;const ji=Symbol(""),Ah=e=>{Bi=e},Lh=()=>Le(ji),Rh=e=>{e.provide(ji,Bi)};var Ih={"/":{title:"Catalog",empty:"No catalog"}};const Ph=q({name:"Catalog",props:{base:{type:String,default:""},level:{type:Number,default:3},index:Boolean,hideHeading:Boolean},setup(e){const t=Lh(),n=sr(Ih),r=ge(),o=Ip(),s=vi(),a=Fe(bs(o.value).map(([i,{meta:u}])=>{const d=t(u);if(!d)return null;const p=i.split("/").length;return{level:Hp(i,"/")?p-2:p-1,base:i.replace(/\/[^/]+\/?$/,"/"),path:i,...d}}).filter(i=>Gr(i)&&xe(i.title))),c=k(()=>{const i=e.base?gd(ti(e.base)):r.value.path.replace(/\/[^/]+$/,"/"),u=i.split("/").length-2,d=[];return a.value.filter(({level:p,path:m})=>{if(!Jn(m,i)||m===i)return!1;if(i==="/"){const g=lr(s.value.locales).filter(E=>E!=="/");if(m==="/404.html"||g.some(E=>Jn(m,E)))return!1}return p-u<=e.level}).sort(({title:p,level:m,order:g},{title:E,level:w,order:b})=>{const S=m-w;return S||(mo(g)?mo(b)?g>0?b>0?g-b:-1:b<0?g-b:1:g:mo(b)?b:p.localeCompare(E))}).forEach(p=>{var E;const{base:m,level:g}=p;switch(g-u){case 1:{d.push(p);break}case 2:{const w=d.find(b=>b.path===m);w&&(w.children??(w.children=[])).push(p);break}default:{const w=d.find(b=>b.path===m.replace(/\/[^/]+\/$/,"/"));if(w){const b=(E=w.children)==null?void 0:E.find(S=>S.path===m);b&&(b.children??(b.children=[])).push(p)}}}}),d});return()=>{const i=c.value.some(u=>u.children);return f("div",{class:["vp-catalog-wrapper",{index:e.index}]},[e.hideHeading?null:f("h2",{class:"vp-catalog-main-title"},n.value.title),c.value.length?f(e.index?"ol":"ul",{class:["vp-catalogs",{deep:i}]},c.value.map(({children:u=[],title:d,path:p,content:m})=>{const g=f(je,{class:"vp-catalog-title",to:p},()=>m?f(m):d);return f("li",{class:"vp-catalog"},i?[f("h3",{id:d,class:["vp-catalog-child-title",{"has-children":u.length}]},[f("a",{href:`#${d}`,class:"vp-catalog-header-anchor","aria-hidden":!0},"#"),g]),u.length?f(e.index?"ol":"ul",{class:"vp-child-catalogs"},u.map(({children:E=[],content:w,path:b,title:S})=>f("li",{class:"vp-child-catalog"},[f("div",{class:["vp-catalog-sub-title",{"has-children":E.length}]},[f("a",{href:`#${S}`,class:"vp-catalog-header-anchor"},"#"),f(je,{class:"vp-catalog-title",to:b},()=>w?f(w):S)]),E.length?f(e.index?"ol":"div",{class:e.index?"vp-sub-catalogs":"vp-sub-catalogs-wrapper"},E.map(({content:y,path:x,title:$})=>e.index?f("li",{class:"vp-sub-catalog"},f(je,{to:x},()=>y?f(y):$)):f(je,{class:"vp-sub-catalog-link",to:x},()=>y?f(y):$))):null]))):null]:f("div",{class:"vp-catalog-child-title"},g))})):f("p",{class:"vp-empty-catalog"},n.value.empty)])}}}),Oh=lt({enhance:({app:e})=>{Rh(e),Dp("Catalog",e)||e.component("Catalog",Ph)}});var Mh={"/":{backToTop:"Back to top"}};const $h=q({name:"BackToTop",setup(e){const t=Se(),n=sr(Mh),r=Fe(),{height:o}=mh(r),{height:s}=yh(),{y:l}=bh(),a=k(()=>t.value.backToTop!==!1&&l.value>100),c=k(()=>l.value/(o.value-s.value)*100);return _e(()=>{r.value=document.body}),()=>f($t,{name:"back-to-top"},()=>a.value?f("button",{type:"button",class:"vp-back-to-top-button","aria-label":n.value.backToTop,onClick:()=>{window.scrollTo({top:0,behavior:"smooth"})}},[f("span",{class:"vp-scroll-progress",role:"progressbar","aria-labelledby":"loadinglabel","aria-valuenow":c.value},f("svg",f("circle",{cx:"50%",cy:"50%",style:{"stroke-dasharray":`calc(${Math.PI*c.value}% - ${4*Math.PI}px) calc(${Math.PI*100}% - ${4*Math.PI}px)`}}))),f("div",{class:"back-to-top-icon"})]):null)}}),Nh=lt({rootComponents:[$h]}),Dh=f("svg",{class:"external-link-icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},[f("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}),f("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"})]),Vi=q({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=xn(),n=k(()=>e.locales[t.value]??{openInNewWindow:"open in new window"});return()=>f("span",[Dh,f("span",{class:"external-link-icon-sr-only"},n.value.openInNewWindow)])}});var Fh={};const Hh=Fh,Bh=lt({enhance({app:e}){e.component("ExternalLinkIcon",f(Vi,{locales:Hh}))}});/** + * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT + */const se={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=se.isStarted();e=yo(e,se.settings.minimum,1),se.status=e===1?null:e;const n=se.render(!t),r=n.querySelector(se.settings.barSelector),o=se.settings.speed,s=se.settings.easing;return n.offsetWidth,jh(l=>{xr(r,{transform:"translate3d("+Vl(e)+"%,0,0)",transition:"all "+o+"ms "+s}),e===1?(xr(n,{transition:"none",opacity:"1"}),n.offsetWidth,setTimeout(function(){xr(n,{transition:"all "+o+"ms linear",opacity:"0"}),setTimeout(function(){se.remove(),l()},o)},o)):setTimeout(()=>l(),o)}),se},isStarted:()=>typeof se.status=="number",start:()=>{se.status||se.set(0);const e=()=>{setTimeout(()=>{se.status&&(se.trickle(),e())},se.settings.trickleSpeed)};return se.settings.trickle&&e(),se},done:e=>!e&&!se.status?se:se.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=se.status;return t?(typeof e!="number"&&(e=(1-t)*yo(Math.random()*t,.1,.95)),t=yo(t+e,0,.994),se.set(t)):se.start()},trickle:()=>se.inc(Math.random()*se.settings.trickleRate),render:e=>{if(se.isRendered())return document.getElementById("nprogress");zl(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=se.settings.template;const n=t.querySelector(se.settings.barSelector),r=e?"-100":Vl(se.status||0),o=document.querySelector(se.settings.parent);return xr(n,{transition:"all 0 linear",transform:"translate3d("+r+"%,0,0)"}),o!==document.body&&zl(o,"nprogress-custom-parent"),o==null||o.appendChild(t),t},remove:()=>{Wl(document.documentElement,"nprogress-busy"),Wl(document.querySelector(se.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&Vh(e)},isRendered:()=>!!document.getElementById("nprogress")},yo=(e,t,n)=>en?n:e,Vl=e=>(-1+e)*100,jh=function(){const e=[];function t(){const n=e.shift();n&&n(t)}return function(n){e.push(n),e.length===1&&t()}}(),xr=function(){const e=["Webkit","O","Moz","ms"],t={};function n(l){return l.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,c){return c.toUpperCase()})}function r(l){const a=document.body.style;if(l in a)return l;let c=e.length;const i=l.charAt(0).toUpperCase()+l.slice(1);let u;for(;c--;)if(u=e[c]+i,u in a)return u;return l}function o(l){return l=n(l),t[l]??(t[l]=r(l))}function s(l,a,c){a=o(a),l.style[a]=c}return function(l,a){for(const c in a){const i=a[c];i!==void 0&&Object.prototype.hasOwnProperty.call(a,c)&&s(l,c,i)}}}(),zi=(e,t)=>(typeof e=="string"?e:xs(e)).indexOf(" "+t+" ")>=0,zl=(e,t)=>{const n=xs(e),r=n+t;zi(n,t)||(e.className=r.substring(1))},Wl=(e,t)=>{const n=xs(e);if(!zi(e,t))return;const r=n.replace(" "+t+" "," ");e.className=r.substring(1,r.length-1)},xs=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),Vh=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},zh=()=>{_e(()=>{const e=Dt(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(n=>{t.has(n.path)||se.start()}),e.afterEach(n=>{t.add(n.path),se.done()})})},Wh=lt({setup(){zh()}}),Uh=JSON.parse(`{"encrypt":{},"author":{"name":"dtp.dev","url":"https://dtp.dev"},"logo":"/logo.png","repo":"chainmovers/dtp","contributors":false,"editLink":false,"pageInfo":false,"breadcrumb":false,"toc":false,"docsDir":"docs/src","locales":{"/":{"lang":"en-US","navbarLocales":{"langName":"English","selectLangAriaLabel":"Select language"},"metaLocales":{"author":"Author","date":"Writing Date","origin":"Original","views":"Page views","category":"Category","tag":"Tag","readingTime":"Reading Time","words":"Words","toc":"On This Page","prev":"Prev","next":"Next","lastUpdated":"Last update","contributors":"Contributors","editLink":"Edit this page on GitHub","print":"Print"},"outlookLocales":{"themeColor":"Theme Color","darkmode":"Theme Mode","fullscreen":"Full Screen"},"routeLocales":{"skipToContent":"Skip to main content","notFoundTitle":"Page not found","notFoundMsg":["There’s nothing here.","How did we get here?","That’s a Four-Oh-Four.","Looks like we've got some broken links."],"back":"Go back","home":"Take me home","openInNewWindow":"Open in new window"},"navbar":[{"icon":"home","text":"","link":"/"},{"text":"Getting Started","link":"/intro.md"},{"text":"Use Cases","link":"/examples/"},{"text":"Docs","link":"/docs/"},{"text":"Community","link":"/community/"}],"sidebar":{"/":["",{"text":"Getting Started","link":"intro.md","children":[{"text":"What is DTP?","link":"intro.md"},{"text":"Installation","link":"how-to/install.md"},{"text":"FAQ","link":"faq.md"}]},{"text":"Use Cases","link":"examples/README.md","children":[{"text":"Examples/Ideas","link":"examples/README.md"},{"text":"RPC Firewall","link":"examples/rpc_firewall.md"},{"text":"Rust Backend","link":"examples/web3_rust.md"}]},{"text":"Docs","link":"docs/README.md","children":[{"text":"Basic Concepts","link":"docs/README.md"},{"text":"API","collapsible":true,"prefix":"docs/","children":[{"text":"Rust","link":"api_rust.md"},{"text":"Typescript","link":"api_typescript.md"},{"text":"'dtp' Command Line","link":"scripts.md"}]},{"text":"Design","link":"docs/design.md"},{"text":"Future Work","link":"docs/future_work.md"}]},{"text":"Community","link":"community/","children":[{"text":"Forums / Contacts","link":"community/"},{"text":"Become an Editor","link":"community/editors.md"}]}]},"footer":"DTP on Github         DTP on Discord","copyright":"Apache 2.0 Open-Source License","displayFooter":true}}}`),qh=te(Uh),Wi=()=>qh,Ui=Symbol(""),Gh=()=>{const e=Le(Ui);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},Kh=(e,t)=>{const{locales:n,...r}=e;return{...r,...n==null?void 0:n[t]}},Yh=lt({enhance({app:e}){const t=Wi(),n=e._context.provides[ms],r=k(()=>Kh(t.value,n.routeLocale.value));e.provide(Ui,r),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return r.value}}})}}),Jh=/\b(?:Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini)/i,Qh=()=>typeof window<"u"&&window.navigator&&"userAgent"in window.navigator&&Jh.test(navigator.userAgent),_o=new Map,Xh=({delay:e=500,duration:t=2e3,locales:n,selector:r,showInMobile:o})=>{const{copy:s}=ih({legacy:!0}),l=sr(n),a=ge(),c=d=>{if(!d.hasAttribute("copy-code-registered")){const p=document.createElement("button");p.type="button",p.classList.add("vp-copy-code-button"),p.innerHTML='
',p.setAttribute("aria-label",l.value.copy),p.setAttribute("data-copied",l.value.copied),d.parentElement&&d.parentElement.insertBefore(p,d),d.setAttribute("copy-code-registered","")}},i=()=>{Qt().then(()=>setTimeout(()=>{r.forEach(d=>{document.querySelectorAll(d).forEach(c)})},e))},u=(d,p,m)=>{let{innerText:g=""}=p;/language-(shellscript|shell|bash|sh|zsh)/.test(d.classList.toString())&&(g=g.replace(/^ *(\$|>) /gm,"")),s(g).then(()=>{m.classList.add("copied"),clearTimeout(_o.get(m));const E=setTimeout(()=>{m.classList.remove("copied"),m.blur(),_o.delete(m)},t);_o.set(m,E)})};_e(()=>{const d=!Qh()||o;d&&i(),Pe("click",p=>{const m=p.target;if(m.matches('div[class*="language-"] > button.copy')){const g=m.parentElement,E=m.nextElementSibling;E&&u(g,E,m)}else if(m.matches('div[class*="language-"] div.vp-copy-icon')){const g=m.parentElement,E=g.parentElement,w=g.nextElementSibling;w&&u(E,w,g)}}),ie(()=>a.value.path,()=>{d&&i()})})};var Zh={"/":{copy:"Copy code",copied:"Copied"}},ev=['.theme-hope-content div[class*="language-"] pre'];const tv=500,nv=2e3,rv=Zh,ov=ev,sv=!1,lv=lt({setup:()=>{Xh({selector:ov,locales:rv,duration:nv,delay:tv,showInMobile:sv})}}),Sr=Es("VUEPRESS_CODE_TAB_STORE",{});var av=q({name:"CodeTabs",props:{active:{type:Number,default:0},data:{type:Array,required:!0},id:{type:String,required:!0},tabId:{type:String,default:""}},slots:Object,setup(e,{slots:t}){const n=te(e.active),r=Fe([]),o=()=>{e.tabId&&(Sr.value[e.tabId]=e.data[n.value].id)},s=(i=n.value)=>{n.value=i{n.value=i>0?i-1:r.value.length-1,r.value[n.value].focus()},a=(i,u)=>{i.key===" "||i.key==="Enter"?(i.preventDefault(),n.value=u):i.key==="ArrowRight"?(i.preventDefault(),s()):i.key==="ArrowLeft"&&(i.preventDefault(),l()),e.tabId&&(Sr.value[e.tabId]=e.data[n.value].id)},c=()=>{if(e.tabId){const i=e.data.findIndex(({id:u})=>Sr.value[e.tabId]===u);if(i!==-1)return i}return e.active};return _e(()=>{n.value=c(),ie(()=>Sr.value[e.tabId],(i,u)=>{if(e.tabId&&i!==u){const d=e.data.findIndex(({id:p})=>p===i);d!==-1&&(n.value=d)}})}),()=>e.data.length?f("div",{class:"vp-code-tabs"},[f("div",{class:"vp-code-tabs-nav",role:"tablist"},e.data.map(({id:i},u)=>{const d=u===n.value;return f("button",{type:"button",ref:p=>{p&&(r.value[u]=p)},class:["vp-code-tab-nav",{active:d}],role:"tab","aria-controls":`codetab-${e.id}-${u}`,"aria-selected":d,onClick:()=>{n.value=u,o()},onKeydown:p=>a(p,u)},t[`title${u}`]({value:i,isActive:d}))})),e.data.map(({id:i},u)=>{const d=u===n.value;return f("div",{class:["vp-code-tab",{active:d}],id:`codetab-${e.id}-${u}`,role:"tabpanel","aria-expanded":d},[f("div",{class:"vp-code-tab-title"},t[`title${u}`]({value:i,isActive:d})),t[`tab${u}`]({value:i,isActive:d})])})]):null}});const qi=({active:e=!1},{slots:t})=>{var n;return f("div",{class:["code-group-item",{active:e}],"aria-selected":e},(n=t.default)==null?void 0:n.call(t))};qi.displayName="CodeGroupItem";const iv=q({name:"CodeGroup",slots:Object,setup(e,{slots:t}){const n=te(-1),r=Fe([]),o=(a=n.value)=>{n.value=a{n.value=a>0?a-1:r.value.length-1,r.value[n.value].focus()},l=(a,c)=>{a.key===" "||a.key==="Enter"?(a.preventDefault(),n.value=c):a.key==="ArrowRight"?(a.preventDefault(),o(c)):a.key==="ArrowLeft"&&(a.preventDefault(),s(c))};return()=>{var c;const a=(((c=t.default)==null?void 0:c.call(t))||[]).filter(i=>i.type.name==="CodeGroupItem").map(i=>(i.props===null&&(i.props={}),i));return a.length===0?null:(n.value<0||n.value>a.length-1?(n.value=a.findIndex(i=>"active"in i.props),n.value===-1&&(n.value=0)):a.forEach((i,u)=>{i.props.active=u===n.value}),f("div",{class:"code-group"},[f("div",{class:"code-group-nav"},a.map((i,u)=>{const d=u===n.value;return f("button",{type:"button",ref:p=>{p&&(r.value[u]=p)},class:["code-group-nav-tab",{active:d}],"aria-pressed":d,"aria-expanded":d,onClick:()=>{n.value=u},onKeydown:p=>l(p,u)},i.props.title)})),a]))}}}),cv=()=>{Pe("beforeprint",()=>{document.querySelectorAll("details").forEach(e=>{e.open=!0})})},wo=Es("VUEPRESS_TAB_STORE",{});var uv=q({name:"Tabs",props:{active:{type:Number,default:0},data:{type:Array,required:!0},id:{type:String,required:!0},tabId:{type:String,default:""}},slots:Object,setup(e,{slots:t}){const n=te(e.active),r=Fe([]),o=()=>{e.tabId&&(wo.value[e.tabId]=e.data[n.value].id)},s=(i=n.value)=>{n.value=i{n.value=i>0?i-1:r.value.length-1,r.value[n.value].focus()},a=(i,u)=>{i.key===" "||i.key==="Enter"?(i.preventDefault(),n.value=u):i.key==="ArrowRight"?(i.preventDefault(),s()):i.key==="ArrowLeft"&&(i.preventDefault(),l()),o()},c=()=>{if(e.tabId){const i=e.data.findIndex(({id:u})=>wo.value[e.tabId]===u);if(i!==-1)return i}return e.active};return _e(()=>{n.value=c(),ie(()=>wo.value[e.tabId],(i,u)=>{if(e.tabId&&i!==u){const d=e.data.findIndex(({id:p})=>p===i);d!==-1&&(n.value=d)}})}),()=>e.data.length?f("div",{class:"vp-tabs"},[f("div",{class:"vp-tabs-nav",role:"tablist"},e.data.map(({id:i},u)=>{const d=u===n.value;return f("button",{type:"button",ref:p=>{p&&(r.value[u]=p)},class:["vp-tab-nav",{active:d}],role:"tab","aria-controls":`tab-${e.id}-${u}`,"aria-selected":d,onClick:()=>{n.value=u,o()},onKeydown:p=>a(p,u)},t[`title${u}`]({value:i,isActive:d}))})),e.data.map(({id:i},u)=>{const d=u===n.value;return f("div",{class:["vp-tab",{active:d}],id:`tab-${e.id}-${u}`,role:"tabpanel","aria-expanded":d},[f("div",{class:"vp-tab-title"},t[`title${u}`]({value:i,isActive:d})),t[`tab${u}`]({value:i,isActive:d})])})]):null}});const fv=lt({enhance:({app:e})=>{e.component("CodeTabs",av),ot("CodeGroup",e)||e.component("CodeGroup",iv),ot("CodeGroupItem",e)||e.component("CodeGroupItem",qi),e.component("Tabs",uv)},setup:()=>{cv()}});let dv={};const Gi=Symbol(""),pv=()=>Le(Gi),hv=e=>{e.provide(Gi,dv)},vv='
',mv=e=>xe(e)?Array.from(document.querySelectorAll(e)):e.map(t=>Array.from(document.querySelectorAll(t))).flat(),Ki=e=>new Promise((t,n)=>{e.complete?t({type:"image",element:e,src:e.src,width:e.naturalWidth,height:e.naturalHeight,alt:e.alt,msrc:e.src}):(e.onload=()=>t(Ki(e)),e.onerror=r=>n(r))}),gv=e=>{const{isSupported:t,toggle:n}=Cs();e.on("uiRegister",()=>{t.value&&e.ui.registerElement({name:"fullscreen",order:7,isButton:!0,html:'',onClick:()=>{n()}}),e.ui.registerElement({name:"download",order:8,isButton:!0,tagName:"a",html:{isCustomSVG:!0,inner:'',outlineID:"pswp__icn-download"},onInit:(r,o)=>{r.setAttribute("download",""),r.setAttribute("target","_blank"),r.setAttribute("rel","noopener"),o.on("change",()=>{r.setAttribute("href",o.currSlide.data.src)})}}),e.ui.registerElement({name:"bulletsIndicator",className:"photo-swipe-bullets-indicator",appendTo:"wrapper",onInit:(r,o)=>{const s=[];let l=-1;for(let a=0;a{o.goTo(s.indexOf(i.target))},s.push(c),r.appendChild(c)}o.on("change",()=>{l>=0&&s[l].classList.remove("active"),s[o.currIndex].classList.add("active"),l=o.currIndex})}})})},bv=(e,t,n=!0)=>fe(()=>import("./photoswipe.esm-SzV8tJDW.js"),__vite__mapDeps([])).then(({default:r})=>{let o=null;const s=e.map(l=>({html:vv,element:l,msrc:l.src}));return e.forEach((l,a)=>{const c=()=>{o==null||o.destroy(),o=new r({preloaderDelay:0,showHideAnimationType:"zoom",...t,dataSource:s,index:a,...n?{closeOnVerticalDrag:!0,wheelToZoom:!1}:{}}),gv(o),o.addFilter("thumbEl",()=>l),o.addFilter("placeholderSrc",()=>l.src),o.init()};l.getAttribute("photo-swipe")||(l.style.cursor="zoom-in",l.addEventListener("click",()=>{c()}),l.addEventListener("keypress",({key:i})=>{i==="Enter"&&c()}),l.setAttribute("photo-swipe","")),Ki(l).then(i=>{s.splice(a,1,i),o==null||o.refreshSlideContent(a)})}),n?Pe("wheel",()=>{o==null||o.close()}):()=>{}}),yv=({selector:e,locales:t,delay:n=500,scrollToClose:r=!0})=>{const o=pv(),s=sr(t),l=ge();let a=null;const c=()=>new Promise(i=>setTimeout(i,n)).then(()=>Qt()).then(async()=>{a=await bv(mv(e),{...o,...s.value},r)});_e(()=>{c(),ie(()=>l.value.path,()=>{a==null||a(),c()})}),En(()=>{a==null||a()})};var _v={"/":{closeTitle:"Close",downloadTitle:"Download Image",fullscreenTitle:"Switch to full screen",zoomTitle:"Zoom in/out",arrowPrevTitle:"Prev (Arrow Left)",arrowNextTitle:"Next (Arrow Right)"}};const wv=".theme-hope-content :not(a) > img:not([no-view])",Ev=_v,Cv=800,xv=!0,Sv=lt({enhance:({app:e})=>{hv(e)},setup:()=>{yv({selector:wv,delay:Cv,locales:Ev,scrollToClose:xv})}}),Yi=()=>{const e=ge();return k(()=>e.value.readingTime??null)},Tv=(e,t)=>{const{minutes:n,words:r}=e,{less1Minute:o,word:s,time:l}=t;return{time:n<1?o:l.replace("$time",Math.round(n).toString()),words:s.replace("$word",r.toString())}};var Ul={"/":{word:"About $word words",less1Minute:"Less than 1 minute",time:"About $time min"}};const ql={words:"",time:""},Bo=typeof Ul>"u"?null:Ul,kv=()=>Bo?sr(Bo):k(()=>null),Av=()=>{if(typeof Bo>"u")return k(()=>ql);const e=Yi(),t=kv();return k(()=>e.value&&t.value?Tv(e.value,t.value):ql)},Tn=()=>Wi(),de=()=>Gh(),cr=()=>{const e=Tn();return k(()=>!!e.value.pure)},Eo=()=>null,Lv="719px",Rv="1440px",Iv="false",Ss={mobileBreakPoint:Lv,pcBreakPoint:Rv,enableThemeColor:Iv},Ts={},Ji=e=>{const{icon:t="",color:n,size:r}=e,o=n||r?{}:null;return n&&(o.color=n),r&&(o.height=Number.isNaN(Number(r))?r:`${r}px`),Xt(t)?f("img",{class:"icon",src:t,alt:"","no-view":"",style:o}):ys(t)?f("img",{class:"icon",src:Ne(t),alt:"","aria-hidden":"","no-view":"",style:o}):f(rt("FontIcon"),e)};Ji.displayName="HopeIcon";var De=Ji;const Pv=()=>{const e=Dt(),t=_t();return n=>{if(n)if(ys(n))t.path!==n&&e.push(n);else if(ni(n))window&&window.open(n);else{const r=t.path.slice(0,t.path.lastIndexOf("/"));e.push(`${r}/${encodeURI(n)}`)}}},Qi=()=>{const e=de(),t=Se();return k(()=>{const{author:n}=t.value;return n?$l(n):n===!1?[]:$l(e.value.author,!1)})},Ov=()=>{const e=Se();return k(()=>Up(e.value.category).map(t=>({name:t,path:""})))},Mv=()=>{const e=Se();return k(()=>qp(e.value.tag).map(t=>({name:t,path:""})))},$v=()=>{const e=Se(),t=ge();return k(()=>{const n=jp(e.value.date);if(n)return n;const{createdTime:r}=t.value.git||{};return r?new Date(r):null})},Nv=()=>{const e=de(),t=ge(),n=Se(),r=Qi(),o=Ov(),s=Mv(),l=$v(),a=Yi(),c=Av(),i=k(()=>({author:r.value,category:o.value,date:l.value,localizedDate:t.value.localizedDate,tag:s.value,isOriginal:n.value.isOriginal||!1,readingTime:a.value,readingTimeLocale:c.value,pageview:"pageview"in n.value?n.value.pageview:!0})),u=k(()=>"pageInfo"in n.value?n.value.pageInfo:"pageInfo"in e.value?e.value.pageInfo:null);return{info:i,items:u}},{mobileBreakPoint:Dv,pcBreakPoint:Fv}=Ss,Gl=e=>e.endsWith("px")?Number(e.slice(0,-2)):null,Zr=()=>{const e=te(!1),t=te(!1),n=()=>{e.value=window.innerWidth<=(Gl(Dv)??719),t.value=window.innerWidth>=(Gl(Fv)??1440)};return _e(()=>{n(),Pe("resize",n,!1),Pe("orientationchange",n,!1)}),{isMobile:e,isPC:t}},Xi=Symbol(""),ur=()=>{const e=Le(Xi);if(!e)throw new Error("useDarkmode() is called without provider.");return e},Hv=e=>{const t=Tn(),n=hh(),r=k(()=>t.value.darkmode||"switch"),o=Es("vuepress-theme-hope-scheme","auto"),s=k(()=>{const a=r.value;return a==="disable"?!1:a==="enable"?!0:a==="auto"?n.value:a==="toggle"?o.value==="dark":o.value==="dark"||o.value==="auto"&&n.value}),l=k(()=>{const a=r.value;return a==="switch"||a==="toggle"});e.provide(Xi,{canToggle:l,config:r,isDarkmode:s,status:o}),Object.defineProperties(e.config.globalProperties,{$isDarkmode:{get:()=>s.value}})},Bv=()=>{const{config:e,isDarkmode:t,status:n}=ur();Sa(()=>{e.value==="disable"?n.value="light":e.value==="enable"?n.value="dark":e.value==="toggle"&&n.value==="auto"&&(n.value="light")}),_e(()=>{ie(t,r=>document.documentElement.setAttribute("data-theme",r?"dark":"light"),{immediate:!0})})};var Ve=q({name:"AutoLink",inheritAttrs:!1,props:{config:{type:Object,required:!0},exact:Boolean,noExternalLinkIcon:Boolean},emits:["focusout"],slots:Object,setup(e,{attrs:t,emit:n,slots:r}){const o=_t(),s=vi(),l=Vr(e,"config"),a=k(()=>Xt(l.value.link)),c=k(()=>!a.value&&ni(l.value.link)),i=k(()=>l.value.target||(a.value?"_blank":void 0)),u=k(()=>i.value==="_blank"),d=k(()=>!a.value&&!c.value&&!u.value),p=k(()=>l.value.rel||(u.value?"noopener noreferrer":null)),m=k(()=>l.value.ariaLabel||l.value.text),g=k(()=>{if(e.exact)return!1;const w=lr(s.value.locales);return w.length?w.every(b=>b!==l.value.link):l.value.link!=="/"}),E=k(()=>d.value?l.value.activeMatch?new RegExp(l.value.activeMatch,"u").test(o.path):g.value?Jn(o.path,l.value.link):o.path===l.value.link:!1);return()=>{const{before:w,after:b,default:S}=r,{text:y,icon:x,link:$}=l.value;return d.value?f(je,{to:$,"aria-label":m.value,...t,class:["nav-link",{active:E.value},t.class],onFocusout:()=>n("focusout")},()=>S?S():[w?w():f(De,{icon:x}),y,b==null?void 0:b()]):f("a",{href:$,rel:p.value,target:i.value,"aria-label":m.value,...t,class:["nav-link",t.class],onFocusout:()=>n("focusout")},S?S():[w?w():f(De,{icon:x}),y,e.noExternalLinkIcon?null:f(Vi),b==null?void 0:b()])}}});const yn=(e,t,n=!1)=>"activeMatch"in t?new RegExp(t.activeMatch,"u").test(e.path):ki(e,t.link)?!0:t.children&&!n?t.children.some(r=>yn(e,r)):!1,Zi=(e,t)=>t.type==="group"?t.children.some(n=>n.type==="group"?Zi(e,n):n.type==="page"&&yn(e,n,!0))||"prefix"in t&&ki(e,t.prefix):!1,ec=(e,t)=>xe(e.link)?f(Ve,{...t,config:e}):f("p",t,[f(De,{icon:e.icon}),e.text]),tc=e=>{const t=_t();return e?f("ul",{class:"vp-sidebar-sub-headers"},e.map(n=>f("li",{class:"vp-sidebar-sub-header"},[ec(n,{class:["vp-sidebar-link","vp-heading",{active:yn(t,n,!0)}]}),tc(n.children)]))):null};var mt=(e=>(e.type="y",e.title="t",e.shortTitle="s",e.icon="i",e.author="a",e.date="d",e.localizedDate="l",e.category="c",e.tag="g",e.isEncrypted="n",e.isOriginal="o",e.readingTime="r",e.excerpt="e",e.sticky="u",e.cover="v",e.index="I",e.order="O",e))(mt||{}),jv=(e=>(e.article="a",e.home="h",e.slide="s",e.page="p",e))(jv||{});const Wt=(e="",t="")=>ys(t)?t:`${ti(e)}${t}`,fn=(e,t=!1)=>{const{meta:n,path:r}=Jr(e);return n?{text:!t&&n[mt.shortTitle]?n[mt.shortTitle]:n[mt.title]||r,link:r,...n[mt.icon]?{icon:n[mt.icon]}:{}}:{text:r,link:r}},eo=(e,t,n)=>n>0?t.map(r=>({type:"heading",text:r.title,link:`${e.path}#${r.slug}`,children:eo(e,r.children,n-1)})):[],jo=({config:e,page:t,headerDepth:n,prefix:r=""})=>{const o=(s,l=r)=>{var c;const a=xe(s)?fn(Wt(l,s)):s.link?{...s,...mn(s.link)?{}:{link:fn(Wt(l,s.link)).link}}:s;if("children"in a){const i=Wt(l,a.prefix),u=a.children==="structure"?Ts[i]:a.children;return{type:"group",...a,prefix:i,children:u.map(d=>o(d,i))}}return{type:"page",...a,children:a.link===t.path?eo(t,((c=t.headers[0])==null?void 0:c.level)===1?t.headers[0].children:t.headers,n):[]}};return e.map(s=>o(s))},Vv=({config:e,page:t,headerDepth:n})=>{const r=lr(e).sort((o,s)=>s.length-o.length);for(const o of r)if(Jn(decodeURI(t.path),o)){const s=e[o];return s?jo({config:s==="structure"?Ts[o]:s==="heading"?eo(t,t.headers,n):s,page:t,headerDepth:n,prefix:o}):[]}return console.warn(`${t.path} is missing sidebar config.`),[]},zv=({config:e,routeLocale:t,page:n,headerDepth:r})=>e==="heading"?eo(n,n.headers,r):e==="structure"?jo({config:Ts[t],page:n,headerDepth:r,prefix:t}):Ho(e)?jo({config:e,page:n,headerDepth:r}):Gr(e)?Vv({config:e,page:n,headerDepth:r}):[],nc=Symbol(""),Wv=()=>{const e=Se(),t=de(),n=ge(),r=xn(),o=k(()=>e.value.home?!1:e.value.sidebar??t.value.sidebar??"structure"),s=k(()=>e.value.headerDepth??t.value.headerDepth??2),l=_s(()=>[o.value,s.value,n.value.path,null],()=>zv({config:o.value,routeLocale:r.value,page:n.value,headerDepth:s.value}));un(nc,l)},ks=()=>{const e=Le(nc);if(!e)throw new Error("useSidebarItems() is called without provider.");return e};var Uv=q({name:"PageFooter",setup(){const e=Tn(),t=de(),n=Se(),r=Qi(),o=k(()=>{const{copyright:i,footer:u}=n.value;return u!==!1&&!!(i||u||t.value.displayFooter)}),s=k(()=>{const{footer:i}=n.value;return i===!1?!1:xe(i)?i:t.value.footer||""}),l=k(()=>r.value.map(({name:i})=>i).join(", ")),a=i=>`Copyright © ${new Date().getFullYear()} ${l.value} ${i?`${i} Licensed`:""}`,c=k(()=>{const{copyright:i,license:u=""}=n.value,{license:d}=e.value,{copyright:p}=t.value;return i??(u?a(u):xe(p)?p:l.value||d?a(d):!1)});return()=>o.value?f("footer",{class:"vp-footer-wrapper"},[s.value?f("div",{class:"vp-footer",innerHTML:s.value}):null,c.value?f("div",{class:"vp-copyright",innerHTML:c.value}):null]):null}}),qv=q({name:"NavbarDropdownLink",props:{config:{type:Object,required:!0}},slots:Object,setup(e,{slots:t}){const n=ge(),r=Vr(e,"config"),o=k(()=>r.value.ariaLabel||r.value.text),s=te(!1);ie(()=>n.value.path,()=>{s.value=!1});const l=a=>{a.detail===0&&(s.value=!s.value)};return()=>{var a;return f("div",{class:["dropdown-wrapper",{open:s.value}]},[f("button",{type:"button",class:"dropdown-title","aria-label":o.value,onClick:l},[((a=t.title)==null?void 0:a.call(t))||f("span",{class:"title"},[f(De,{icon:r.value.icon}),e.config.text]),f("span",{class:"arrow"}),f("ul",{class:"nav-dropdown"},r.value.children.map((c,i)=>{const u=i===r.value.children.length-1;return f("li",{class:"dropdown-item"},"children"in c?[f("h4",{class:"dropdown-subtitle"},c.link?f(Ve,{config:c,onFocusout:()=>{c.children.length===0&&u&&(s.value=!1)}}):f("span",c.text)),f("ul",{class:"dropdown-subitem-wrapper"},c.children.map((d,p)=>f("li",{class:"dropdown-subitem"},f(Ve,{config:d,onFocusout:()=>{p===c.children.length-1&&u&&(s.value=!1)}}))))]:f(Ve,{config:c,onFocusout:()=>{u&&(s.value=!1)}}))}))])])}}});const rc=(e,t="")=>xe(e)?fn(Wt(t,e)):"children"in e?{...e,...e.link&&!mn(e.link)?fn(Wt(t,e.link)):{},children:e.children.map(n=>rc(n,Wt(t,e.prefix)))}:{...e,link:mn(e.link)?e.link:fn(Wt(t,e.link)).link},oc=()=>{const e=de(),t=()=>(e.value.navbar||[]).map(n=>rc(n));return _s(()=>e.value.navbar,()=>t())},Gv=()=>{const e=de(),t=k(()=>e.value.repo||null),n=k(()=>t.value?zp(t.value):null),r=k(()=>t.value?Ai(t.value):null),o=k(()=>n.value?e.value.repoLabel??(r.value===null?"Source":r.value):null);return k(()=>!n.value||!o.value||e.value.repoDisplay===!1?null:{type:r.value||"Source",label:o.value,link:n.value})};var Kv=q({name:"NavScreenDropdown",props:{config:{type:Object,required:!0}},setup(e){const t=ge(),n=Vr(e,"config"),r=k(()=>n.value.ariaLabel||n.value.text),o=te(!1);ie(()=>t.value.path,()=>{o.value=!1});const s=(l,a)=>a[a.length-1]===l;return()=>[f("button",{type:"button",class:["nav-screen-dropdown-title",{active:o.value}],"aria-label":r.value,onClick:()=>{o.value=!o.value}},[f("span",{class:"title"},[f(De,{icon:n.value.icon}),e.config.text]),f("span",{class:["arrow",o.value?"down":"end"]})]),f("ul",{class:["nav-screen-dropdown",{hide:!o.value}]},n.value.children.map(l=>f("li",{class:"dropdown-item"},"children"in l?[f("h4",{class:"dropdown-subtitle"},l.link?f(Ve,{config:l,onFocusout:()=>{s(l,n.value.children)&&l.children.length===0&&(o.value=!1)}}):f("span",l.text)),f("ul",{class:"dropdown-subitem-wrapper"},l.children.map(a=>f("li",{class:"dropdown-subitem"},f(Ve,{config:a,onFocusout:()=>{s(a,l.children)&&s(l,n.value.children)&&(o.value=!1)}}))))]:f(Ve,{config:l,onFocusout:()=>{s(l,n.value.children)&&(o.value=!1)}}))))]}}),Yv=q({name:"NavScreenLinks",setup(){const e=oc();return()=>e.value.length?f("nav",{class:"nav-screen-links"},e.value.map(t=>f("div",{class:"navbar-links-item"},"children"in t?f(Kv,{config:t}):f(Ve,{config:t})))):null}});const sc=()=>f(Ee,{name:"dark"},()=>f("path",{d:"M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"}));sc.displayName="DarkIcon";const lc=()=>f(Ee,{name:"light"},()=>f("path",{d:"M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"}));lc.displayName="LightIcon";const ac=()=>f(Ee,{name:"auto"},()=>f("path",{d:"M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"}));ac.displayName="AutoIcon";const ic=()=>f(Ee,{name:"enter-fullscreen"},()=>f("path",{d:"M762.773 90.24h-497.28c-96.106 0-174.4 78.293-174.4 174.4v497.28c0 96.107 78.294 174.4 174.4 174.4h497.28c96.107 0 175.04-78.293 174.4-174.4V264.64c0-96.213-78.186-174.4-174.4-174.4zm-387.2 761.173H215.04c-21.867 0-40.427-17.92-41.067-41.066V649.92c0-22.507 17.92-40.427 40.427-40.427 11.307 0 21.227 4.694 28.48 11.947 7.253 7.253 11.947 17.92 11.947 28.48v62.293l145.28-145.28c15.893-15.893 41.813-15.893 57.706 0 15.894 15.894 15.894 41.814 0 57.707l-145.28 145.28h62.294c22.506 0 40.426 17.92 40.426 40.427s-17.173 41.066-39.68 41.066zM650.24 165.76h160.427c21.866 0 40.426 17.92 41.066 41.067v160.426c0 22.507-17.92 40.427-40.426 40.427-11.307 0-21.227-4.693-28.48-11.947-7.254-7.253-11.947-17.92-11.947-28.48v-62.186L625.6 450.347c-15.893 15.893-41.813 15.893-57.707 0-15.893-15.894-15.893-41.814 0-57.707l145.28-145.28H650.88c-22.507 0-40.427-17.92-40.427-40.427s17.174-41.173 39.787-41.173z"}));ic.displayName="EnterFullScreenIcon";const cc=()=>f(Ee,{name:"cancel-fullscreen"},()=>f("path",{d:"M778.468 78.62H247.922c-102.514 0-186.027 83.513-186.027 186.027V795.08c0 102.514 83.513 186.027 186.027 186.027h530.432c102.514 0 186.71-83.513 186.026-186.027V264.647C964.494 162.02 880.981 78.62 778.468 78.62zM250.88 574.35h171.122c23.324 0 43.122 19.115 43.804 43.805v171.121c0 24.008-19.114 43.122-43.122 43.122-12.06 0-22.641-5.006-30.378-12.743s-12.743-19.115-12.743-30.379V722.83L224.597 877.91c-16.953 16.952-44.6 16.952-61.553 0-16.953-16.954-16.953-44.602 0-61.554L318.009 661.39h-66.446c-24.007 0-43.122-19.114-43.122-43.122 0-24.12 18.432-43.918 42.439-43.918zm521.899-98.873H601.657c-23.325 0-43.122-19.114-43.805-43.804V260.55c0-24.007 19.115-43.122 43.122-43.122 12.06 0 22.642 5.007 30.379 12.743s12.743 19.115 12.743 30.38v66.445l154.965-154.965c16.953-16.953 44.601-16.953 61.554 0 16.953 16.953 16.953 44.6 0 61.554L705.536 388.55h66.446c24.007 0 43.122 19.115 43.122 43.122.114 24.007-18.318 43.804-42.325 43.804z"}));cc.displayName="CancelFullScreenIcon";const uc=()=>f(Ee,{name:"outlook"},()=>[f("path",{d:"M224 800c0 9.6 3.2 44.8 6.4 54.4 6.4 48-48 76.8-48 76.8s80 41.6 147.2 0 134.4-134.4 38.4-195.2c-22.4-12.8-41.6-19.2-57.6-19.2C259.2 716.8 227.2 761.6 224 800zM560 675.2l-32 51.2c-51.2 51.2-83.2 32-83.2 32 25.6 67.2 0 112-12.8 128 25.6 6.4 51.2 9.6 80 9.6 54.4 0 102.4-9.6 150.4-32l0 0c3.2 0 3.2-3.2 3.2-3.2 22.4-16 12.8-35.2 6.4-44.8-9.6-12.8-12.8-25.6-12.8-41.6 0-54.4 60.8-99.2 137.6-99.2 6.4 0 12.8 0 22.4 0 12.8 0 38.4 9.6 48-25.6 0-3.2 0-3.2 3.2-6.4 0-3.2 3.2-6.4 3.2-6.4 6.4-16 6.4-16 6.4-19.2 9.6-35.2 16-73.6 16-115.2 0-105.6-41.6-198.4-108.8-268.8C704 396.8 560 675.2 560 675.2zM224 419.2c0-28.8 22.4-51.2 51.2-51.2 28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2C246.4 470.4 224 448 224 419.2zM320 284.8c0-22.4 19.2-41.6 41.6-41.6 22.4 0 41.6 19.2 41.6 41.6 0 22.4-19.2 41.6-41.6 41.6C339.2 326.4 320 307.2 320 284.8zM457.6 208c0-12.8 12.8-25.6 25.6-25.6 12.8 0 25.6 12.8 25.6 25.6 0 12.8-12.8 25.6-25.6 25.6C470.4 233.6 457.6 220.8 457.6 208zM128 505.6C128 592 153.6 672 201.6 736c28.8-60.8 112-60.8 124.8-60.8-16-51.2 16-99.2 16-99.2l316.8-422.4c-48-19.2-99.2-32-150.4-32C297.6 118.4 128 291.2 128 505.6zM764.8 86.4c-22.4 19.2-390.4 518.4-390.4 518.4-22.4 28.8-12.8 76.8 22.4 99.2l9.6 6.4c35.2 22.4 80 12.8 99.2-25.6 0 0 6.4-12.8 9.6-19.2 54.4-105.6 275.2-524.8 288-553.6 6.4-19.2-3.2-32-19.2-32C777.6 76.8 771.2 80 764.8 86.4z"})]);uc.displayName="OutlookIcon";var fc=q({name:"AppearanceSwitch",setup(){const{config:e,isDarkmode:t,status:n}=ur(),r=cr(),o=()=>{e.value==="switch"?n.value={light:"dark",dark:"auto",auto:"light"}[n.value]:n.value=n.value==="light"?"dark":"light"},s=async l=>{if(!(document.startViewTransition&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&!r.value)||!l){o();return}const a=l.clientX,c=l.clientY,i=Math.hypot(Math.max(a,innerWidth-a),Math.max(c,innerHeight-c)),u=t.value;await document.startViewTransition(async()=>{o(),await Qt()}).ready,t.value!==u&&document.documentElement.animate({clipPath:t.value?[`circle(${i}px at ${a}px ${c}px)`,`circle(0px at ${a}px ${c}px)`]:[`circle(0px at ${a}px ${c}px)`,`circle(${i}px at ${a}px ${c}px)`]},{duration:400,pseudoElement:t.value?"::view-transition-old(root)":"::view-transition-new(root)"})};return()=>f("button",{type:"button",id:"appearance-switch",onClick:s},[f(ac,{style:{display:n.value==="auto"?"block":"none"}}),f(sc,{style:{display:n.value==="dark"?"block":"none"}}),f(lc,{style:{display:n.value==="light"?"block":"none"}})])}}),Jv=q({name:"AppearanceMode",setup(){const e=de(),{canToggle:t}=ur(),n=k(()=>e.value.outlookLocales.darkmode);return()=>t.value?f("div",{class:"appearance-wrapper"},[f("label",{class:"appearance-title",for:"appearance-switch"},n.value),f(fc)]):null}});const Co="VUEPRESS_THEME_COLOR";var Qv=q({name:"ThemeColorPicker",props:{themeColor:{type:Object,required:!0}},setup(e){const t=(n="")=>{const r=document.documentElement.classList,o=lr(e.themeColor);if(!n){localStorage.removeItem(Co),r.remove(...o);return}r.remove(...o.filter(s=>s!==n)),r.add(n),localStorage.setItem(Co,n)};return _e(()=>{const n=localStorage.getItem(Co);n&&t(n)}),()=>f("ul",{id:"theme-color-picker"},[f("li",f("span",{class:"theme-color",onClick:()=>t()})),bs(e.themeColor).map(([n,r])=>f("li",f("span",{style:{background:r},onClick:()=>t(n)})))])}});const dn=Ss.enableThemeColor==="true",Xv=dn?Bp(bs(Ss).filter(([e])=>e.startsWith("theme-"))):{};var Zv=q({name:"ThemeColor",setup(){const e=de(),t=k(()=>e.value.outlookLocales.themeColor);return()=>dn?f("div",{class:"theme-color-wrapper"},[f("label",{class:"theme-color-title",for:"theme-color-picker"},t.value),f(Qv,{themeColor:Xv})]):null}}),dc=q({name:"ToggleFullScreenButton",setup(){const e=de(),{isSupported:t,isFullscreen:n,toggle:r}=Cs(),o=k(()=>e.value.outlookLocales.fullscreen);return()=>t?f("div",{class:"full-screen-wrapper"},[f("label",{class:"full-screen-title",for:"full-screen-switch"},o.value),f("button",{type:"button",id:"full-screen-switch",class:"full-screen",ariaPressed:n.value,onClick:()=>r()},n.value?f(cc):f(ic))]):null}}),pc=q({name:"OutlookSettings",setup(){const e=Tn(),t=cr(),n=k(()=>!t.value&&e.value.fullscreen);return()=>f(Qr,()=>[dn?f(Zv):null,f(Jv),n.value?f(dc):null])}}),em=q({name:"NavScreen",props:{show:Boolean},emits:["close"],slots:Object,setup(e,{emit:t,slots:n}){const r=ge(),{isMobile:o}=Zr(),s=Fe(),l=Di(s);return _e(()=>{s.value=document.body,ie(o,a=>{!a&&e.show&&(l.value=!1,t("close"))}),ie(()=>r.value.path,()=>{l.value=!1,t("close")})}),En(()=>{l.value=!1}),()=>f($t,{name:"fade",onEnter:()=>{l.value=!0},onAfterLeave:()=>{l.value=!1}},()=>{var a,c;return e.show?f("div",{id:"nav-screen"},f("div",{class:"vp-nav-screen-container"},[(a=n.before)==null?void 0:a.call(n),f(Yv),f("div",{class:"vp-outlook-wrapper"},f(pc)),(c=n.after)==null?void 0:c.call(n)])):null})}}),tm=q({name:"NavbarBrand",setup(){const e=xn(),t=gs(),n=de(),r=k(()=>n.value.home||e.value),o=k(()=>t.value.title),s=k(()=>n.value.navTitle??o.value),l=k(()=>n.value.logo?Ne(n.value.logo):null),a=k(()=>n.value.logoDark?Ne(n.value.logoDark):null);return()=>f(je,{to:r.value,class:"vp-brand"},()=>[l.value?f("img",{class:["vp-nav-logo",{light:!!a.value}],src:l.value,alt:""}):null,a.value?f("img",{class:["vp-nav-logo dark"],src:a.value,alt:""}):null,s.value?f("span",{class:["vp-site-name",{"hide-in-pad":l.value&&n.value.hideSiteNameOnMobile!==!1}]},s.value):null])}}),nm=q({name:"NavbarLinks",setup(){const e=oc();return()=>e.value.length?f("nav",{class:"vp-nav-links"},e.value.map(t=>f("div",{class:"nav-item hide-in-mobile"},"children"in t?f(qv,{config:t}):f(Ve,{config:t})))):null}}),rm=q({name:"RepoLink",components:{BitbucketIcon:Ci,GiteeIcon:Ei,GitHubIcon:_i,GitLabIcon:wi,SourceIcon:xi},setup(){const e=Gv();return()=>e.value?f("div",{class:"nav-item vp-repo"},f("a",{class:"vp-repo-link",href:e.value.link,target:"_blank",rel:"noopener noreferrer","aria-label":e.value.label},f(rt(`${e.value.type}Icon`),{style:{width:"1.25rem",height:"1.25rem",verticalAlign:"middle"}}))):null}});const hc=({active:e=!1},{emit:t})=>f("button",{type:"button",class:["vp-toggle-navbar-button",{"is-active":e}],"aria-label":"Toggle Navbar","aria-expanded":e,"aria-controls":"nav-screen",onClick:()=>t("toggle")},f("span",[f("span",{class:"vp-top"}),f("span",{class:"vp-middle"}),f("span",{class:"vp-bottom"})]));hc.displayName="ToggleNavbarButton";var om=hc;const Vo=(e,{emit:t})=>f("button",{type:"button",class:"vp-toggle-sidebar-button",title:"Toggle Sidebar",onClick:()=>t("toggle")},f("span",{class:"icon"}));Vo.displayName="ToggleSidebarButton",Vo.emits=["toggle"];var sm=Vo,lm=q({name:"OutlookButton",setup(){const{isSupported:e}=Cs(),t=Tn(),n=cr(),r=ge(),{canToggle:o}=ur(),s=te(!1),l=k(()=>!n.value&&t.value.fullscreen&&e);return ie(()=>r.value.path,()=>{s.value=!1}),()=>o.value||l.value||dn?f("div",{class:"nav-item hide-in-mobile"},o.value&&!l.value&&!dn?f(fc):l.value&&!o.value&&!dn?f(dc):f("button",{type:"button",class:["outlook-button",{open:s.value}],tabindex:"-1","aria-hidden":!0},[f(uc),f("div",{class:"outlook-dropdown"},f(pc))])):null}}),am=q({name:"NavBar",emits:["toggleSidebar"],slots:Object,setup(e,{emit:t,slots:n}){const r=de(),{isMobile:o}=Zr(),s=te(!1),l=k(()=>{const{navbarAutoHide:u="mobile"}=r.value;return u!=="none"&&(u==="always"||o.value)}),a=k(()=>r.value.navbarLayout||{start:["Brand"],center:["Links"],end:["Language","Repo","Outlook","Search"]}),c={Brand:tm,Language:Eo,Links:nm,Repo:rm,Outlook:lm,Search:ot("Docsearch")?rt("Docsearch"):ot("SearchBox")?rt("SearchBox"):Eo},i=u=>c[u]??(ot(u)?rt(u):Eo);return()=>{var u,d,p,m,g,E;return[f("header",{id:"navbar",class:["vp-navbar",{"auto-hide":l.value,"hide-icon":r.value.navbarIcon===!1}]},[f("div",{class:"vp-navbar-start"},[f(sm,{onToggle:()=>{s.value&&(s.value=!1),t("toggleSidebar")}}),(u=n.startBefore)==null?void 0:u.call(n),(a.value.start||[]).map(w=>f(i(w))),(d=n.startAfter)==null?void 0:d.call(n)]),f("div",{class:"vp-navbar-center"},[(p=n.centerBefore)==null?void 0:p.call(n),(a.value.center||[]).map(w=>f(i(w))),(m=n.centerAfter)==null?void 0:m.call(n)]),f("div",{class:"vp-navbar-end"},[(g=n.endBefore)==null?void 0:g.call(n),(a.value.end||[]).map(w=>f(i(w))),(E=n.endAfter)==null?void 0:E.call(n),f(om,{active:s.value,onToggle:()=>{s.value=!s.value}})])]),f(em,{show:s.value,onClose:()=>{s.value=!1}},{before:()=>{var w;return(w=n.screenTop)==null?void 0:w.call(n)},after:()=>{var w;return(w=n.screenBottom)==null?void 0:w.call(n)}})]}}}),im=q({name:"SidebarChild",props:{config:{type:Object,required:!0}},setup(e){const t=_t();return()=>[ec(e.config,{class:["vp-sidebar-link",`vp-sidebar-${e.config.type}`,{active:yn(t,e.config,!0)}],exact:!0}),tc(e.config.children)]}}),cm=q({name:"SidebarGroup",props:{config:{type:Object,required:!0},open:{type:Boolean,required:!0}},emits:["toggle"],setup(e,{emit:t}){const n=_t(),r=k(()=>yn(n,e.config)),o=k(()=>yn(n,e.config,!0));return()=>{const{collapsible:s,children:l=[],icon:a,prefix:c,link:i,text:u}=e.config;return f("section",{class:"vp-sidebar-group"},[f(s?"button":"p",{class:["vp-sidebar-heading",{clickable:s||i,exact:o.value,active:r.value}],...s?{type:"button",onClick:()=>t("toggle"),onKeydown:d=>{d.key==="Enter"&&t("toggle")}}:{}},[f(De,{icon:a}),i?f(Ve,{class:"vp-sidebar-title",config:{text:u,link:i},noExternalLinkIcon:!0}):f("span",{class:"vp-sidebar-title"},u),s?f("span",{class:["vp-arrow",e.open?"down":"end"]}):null]),e.open||!s?f(vc,{key:c,config:l}):null])}}}),vc=q({name:"SidebarLinks",props:{config:{type:Array,required:!0}},setup(e){const t=_t(),n=te(-1),r=o=>{n.value=o===n.value?-1:o};return ie(()=>t.path,()=>{const o=e.config.findIndex(s=>Zi(t,s));n.value=o},{immediate:!0,flush:"post"}),()=>f("ul",{class:"vp-sidebar-links"},e.config.map((o,s)=>f("li",o.type==="group"?f(cm,{config:o,open:s===n.value,onToggle:()=>r(s)}):f(im,{config:o}))))}}),um=q({name:"SideBar",slots:Object,setup(e,{slots:t}){const n=_t(),r=de(),o=ks(),s=Fe();return _e(()=>{ie(()=>n.hash,l=>{const a=document.querySelector(`.vp-sidebar a.vp-sidebar-link[href="${n.path}${l}"]`);if(!a)return;const{top:c,height:i}=s.value.getBoundingClientRect(),{top:u,height:d}=a.getBoundingClientRect();uc+i&&a.scrollIntoView(!1)},{immediate:!0})}),()=>{var l,a,c;return f("aside",{ref:s,id:"sidebar",class:["vp-sidebar",{"hide-icon":r.value.sidebarIcon===!1}]},[(l=t.top)==null?void 0:l.call(t),((a=t.default)==null?void 0:a.call(t))||f(vc,{config:o.value}),(c=t.bottom)==null?void 0:c.call(t)])}}}),mc=q({name:"CommonWrapper",props:{containerClass:{type:String,default:""},noNavbar:Boolean,noSidebar:Boolean,noToc:Boolean},slots:Object,setup(e,{slots:t}){const n=Dt(),r=ge(),o=Se(),s=de(),{isMobile:l,isPC:a}=Zr(),[c,i]=Dl(!1),[u,d]=Dl(!1),p=ks(),m=te(!1),g=k(()=>e.noNavbar||o.value.navbar===!1||s.value.navbar===!1?!1:!!(r.value.title||s.value.logo||s.value.repo||s.value.navbar)),E=k(()=>e.noSidebar?!1:o.value.sidebar!==!1&&p.value.length!==0&&!o.value.home),w=k(()=>e.noToc||o.value.home?!1:o.value.toc||s.value.toc!==!1&&o.value.toc!==!1),b={x:0,y:0},S=C=>{b.x=C.changedTouches[0].clientX,b.y=C.changedTouches[0].clientY},y=C=>{const M=C.changedTouches[0].clientX-b.x,I=C.changedTouches[0].clientY-b.y;Math.abs(M)>Math.abs(I)*1.5&&Math.abs(M)>40&&(M>0&&b.x<=80?i(!0):i(!1))},x=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;let $=0;return Pe("scroll",nh(()=>{const C=x();C<=58||C<$?m.value=!1:$+200{C||i(!1)}),_e(()=>{const C=Di(document.body);ie(c,I=>{C.value=I});const M=n.afterEach(()=>{i(!1)});En(()=>{C.value=!1,M()})}),()=>f(ot("GlobalEncrypt")?rt("GlobalEncrypt"):yi,()=>f("div",{class:["theme-container",{"no-navbar":!g.value,"no-sidebar":!E.value&&!(t.sidebar||t.sidebarTop||t.sidebarBottom),"has-toc":w.value,"hide-navbar":m.value,"sidebar-collapsed":!l.value&&!a.value&&u.value,"sidebar-open":l.value&&c.value},e.containerClass,o.value.containerClass||""],onTouchStart:S,onTouchEnd:y},[g.value?f(am,{onToggleSidebar:()=>i()},{startBefore:()=>{var C;return(C=t.navbarStartBefore)==null?void 0:C.call(t)},startAfter:()=>{var C;return(C=t.navbarStartAfter)==null?void 0:C.call(t)},centerBefore:()=>{var C;return(C=t.navbarCenterBefore)==null?void 0:C.call(t)},centerAfter:()=>{var C;return(C=t.navbarCenterAfter)==null?void 0:C.call(t)},endBefore:()=>{var C;return(C=t.navbarEndBefore)==null?void 0:C.call(t)},endAfter:()=>{var C;return(C=t.navbarEndAfter)==null?void 0:C.call(t)},screenTop:()=>{var C;return(C=t.navScreenTop)==null?void 0:C.call(t)},screenBottom:()=>{var C;return(C=t.navScreenBottom)==null?void 0:C.call(t)}}):null,f($t,{name:"fade"},()=>c.value?f("div",{class:"vp-sidebar-mask",onClick:()=>i(!1)}):null),f($t,{name:"fade"},()=>l.value?null:f("div",{class:"toggle-sidebar-wrapper",onClick:()=>d()},f("span",{class:["arrow",u.value?"end":"start"]}))),f(um,{},{...t.sidebar?{default:()=>t.sidebar()}:{},top:()=>{var C;return(C=t.sidebarTop)==null?void 0:C.call(t)},bottom:()=>{var C;return(C=t.sidebarBottom)==null?void 0:C.call(t)}}),t.default(),f(Uv)]))}}),on=q({name:"DropTransition",props:{type:{type:String,default:"single"},delay:{type:Number,default:0},duration:{type:Number,default:.25},appear:Boolean},slots:Object,setup(e,{slots:t}){const n=o=>{o.style.transition=`transform ${e.duration}s ease-in-out ${e.delay}s, opacity ${e.duration}s ease-in-out ${e.delay}s`,o.style.transform="translateY(-20px)",o.style.opacity="0"},r=o=>{o.style.transform="translateY(0)",o.style.opacity="1"};return()=>f(e.type==="single"?$t:rd,{name:"drop",appear:e.appear,onAppear:n,onAfterAppear:r,onEnter:n,onAfterEnter:r,onBeforeLeave:n},()=>t.default())}});const zo=({custom:e})=>f(bi,{class:["theme-hope-content",{custom:e}]});zo.displayName="MarkdownContent",zo.props={custom:Boolean};var gc=zo;const bc=()=>f(Ee,{name:"author"},()=>f("path",{d:"M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"}));bc.displayName="AuthorIcon";const yc=()=>f(Ee,{name:"calendar"},()=>f("path",{d:"M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"}));yc.displayName="CalendarIcon";const _c=()=>f(Ee,{name:"category"},()=>f("path",{d:"M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"}));_c.displayName="CategoryIcon";const wc=()=>f(Ee,{name:"print"},()=>f("path",{d:"M819.2 364.8h-44.8V128c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v236.8h-44.8C145.067 364.8 96 413.867 96 473.6v192c0 59.733 49.067 108.8 108.8 108.8h44.8V896c0 17.067 14.933 32 32 32h460.8c17.067 0 32-14.933 32-32V774.4h44.8c59.733 0 108.8-49.067 108.8-108.8v-192c0-59.733-49.067-108.8-108.8-108.8zM313.6 160h396.8v204.8H313.6V160zm396.8 704H313.6V620.8h396.8V864zM864 665.6c0 25.6-19.2 44.8-44.8 44.8h-44.8V588.8c0-17.067-14.933-32-32-32H281.6c-17.067 0-32 14.933-32 32v121.6h-44.8c-25.6 0-44.8-19.2-44.8-44.8v-192c0-25.6 19.2-44.8 44.8-44.8h614.4c25.6 0 44.8 19.2 44.8 44.8v192z"}));wc.displayName="PrintIcon";const Ec=()=>f(Ee,{name:"tag"},()=>f("path",{d:"M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"}));Ec.displayName="TagIcon";const Cc=()=>f(Ee,{name:"timer"},()=>f("path",{d:"M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"}));Cc.displayName="TimerIcon";const xc=()=>f(Ee,{name:"word"},()=>[f("path",{d:"M518.217 432.64V73.143A73.143 73.143 0 01603.43 1.097a512 512 0 01419.474 419.474 73.143 73.143 0 01-72.046 85.212H591.36a73.143 73.143 0 01-73.143-73.143z"}),f("path",{d:"M493.714 566.857h340.297a73.143 73.143 0 0173.143 85.577A457.143 457.143 0 11371.566 117.76a73.143 73.143 0 0185.577 73.143v339.383a36.571 36.571 0 0036.571 36.571z"})]);xc.displayName="WordIcon";const Ft=()=>{const e=de();return k(()=>e.value.metaLocales)};var fm=q({name:"AuthorInfo",inheritAttrs:!1,props:{author:{type:Array,required:!0},pure:Boolean},setup(e){const t=Ft();return()=>e.author.length?f("span",{class:"page-author-info","aria-label":`${t.value.author}${e.pure?"":"🖊"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(bc),f("span",e.author.map(n=>n.url?f("a",{class:"page-author-item",href:n.url,target:"_blank",rel:"noopener noreferrer"},n.name):f("span",{class:"page-author-item"},n.name))),f("span",{property:"author",content:e.author.map(n=>n.name).join(", ")})]):null}}),dm=q({name:"CategoryInfo",inheritAttrs:!1,props:{category:{type:Array,required:!0},pure:Boolean},setup(e){const t=Dt(),n=ge(),r=Ft(),o=(s,l="")=>{l&&n.value.path!==l&&(s.preventDefault(),t.push(l))};return()=>e.category.length?f("span",{class:"page-category-info","aria-label":`${r.value.category}${e.pure?"":"🌈"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(_c),e.category.map(({name:s,path:l})=>f("span",{class:["page-category-item",{[`category${Si(s,9)}`]:!e.pure,clickable:l}],role:l?"navigation":"",onClick:a=>o(a,l)},s)),f("meta",{property:"articleSection",content:e.category.map(({name:s})=>s).join(",")})]):null}}),pm=q({name:"DateInfo",inheritAttrs:!1,props:{date:{type:Object,default:null},localizedDate:{type:String,default:""},pure:Boolean},setup(e){const t=hi(),n=Ft();return()=>e.date?f("span",{class:"page-date-info","aria-label":`${n.value.date}${e.pure?"":"📅"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(yc),f("span",f(Qr,()=>e.localizedDate||e.date.toLocaleDateString(t.value))),f("meta",{property:"datePublished",content:e.date.toISOString()||""})]):null}}),hm=q({name:"OriginalInfo",inheritAttrs:!1,props:{isOriginal:Boolean},setup(e){const t=Ft();return()=>e.isOriginal?f("span",{class:"page-original-info"},t.value.origin):null}}),vm=q({name:"ReadingTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=Ft(),n=k(()=>{if(!e.readingTime)return null;const{minutes:r}=e.readingTime;return r<1?"PT1M":`PT${Math.round(r)}M`});return()=>{var r,o;return(r=e.readingTimeLocale)!=null&&r.time?f("span",{class:"page-reading-time-info","aria-label":`${t.value.readingTime}${e.pure?"":"⌛"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(Cc),f("span",(o=e.readingTimeLocale)==null?void 0:o.time),f("meta",{property:"timeRequired",content:n.value})]):null}}}),mm=q({name:"TagInfo",inheritAttrs:!1,props:{tag:{type:Array,default:()=>[]},pure:Boolean},setup(e){const t=Dt(),n=ge(),r=Ft(),o=(s,l="")=>{l&&n.value.path!==l&&(s.preventDefault(),t.push(l))};return()=>e.tag.length?f("span",{class:"page-tag-info","aria-label":`${r.value.tag}${e.pure?"":"🏷"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(Ec),e.tag.map(({name:s,path:l})=>f("span",{class:["page-tag-item",{[`tag${Si(s,9)}`]:!e.pure,clickable:l}],role:l?"navigation":"",onClick:a=>o(a,l)},s)),f("meta",{property:"keywords",content:e.tag.map(({name:s})=>s).join(",")})]):null}}),gm=q({name:"ReadTimeInfo",inheritAttrs:!1,props:{readingTime:{type:Object,default:()=>null},readingTimeLocale:{type:Object,default:()=>null},pure:Boolean},setup(e){const t=Ft();return()=>{var n,r,o;return(n=e.readingTimeLocale)!=null&&n.words?f("span",{class:"page-word-info","aria-label":`${t.value.words}${e.pure?"":"🔠"}`,...e.pure?{}:{"data-balloon-pos":"down"}},[f(xc),f("span",(r=e.readingTimeLocale)==null?void 0:r.words),f("meta",{property:"wordCount",content:(o=e.readingTime)==null?void 0:o.words})]):null}}}),bm=q({name:"PageInfo",components:{AuthorInfo:fm,CategoryInfo:dm,DateInfo:pm,OriginalInfo:hm,PageViewInfo:()=>null,ReadingTimeInfo:vm,TagInfo:mm,WordInfo:gm},props:{items:{type:[Array,Boolean],default:()=>["Author","Original","Date","PageView","ReadingTime","Category","Tag"]},info:{type:Object,required:!0}},setup(e){const t=cr();return()=>e.items?f("div",{class:"page-info"},e.items.map(n=>f(rt(`${n}Info`),{...e.info,pure:t.value}))):null}}),ym=q({name:"PrintButton",setup(){const e=Tn(),t=de();return()=>e.value.print===!1?null:f("button",{type:"button",class:"print-button",title:t.value.metaLocales.print,onClick:()=>{window.print()}},f(wc))}});const _m=({title:e,level:t,slug:n})=>f(je,{to:`#${n}`,class:["toc-link",`level${t}`]},()=>e),Wo=(e,t)=>{const n=_t();return e.length&&t>0?f("ul",{class:"toc-list"},e.map(r=>{const o=Wo(r.children,t-1);return[f("li",{class:["toc-item",{active:n.hash===`#${r.slug}`}]},_m(r)),o?f("li",o):null]})):null};var wm=q({name:"TOC",props:{items:{type:Array,default:()=>[]},headerDepth:{type:Number,default:2}},slots:Object,setup(e,{slots:t}){const n=_t(),r=ge(),o=Ft(),s=Fe(),l=te("-1.7rem"),a=i=>{var u;(u=s.value)==null||u.scrollTo({top:i,behavior:"smooth"})},c=()=>{if(s.value){const i=document.querySelector(".toc-item.active");i?l.value=`${i.getBoundingClientRect().top-s.value.getBoundingClientRect().top+s.value.scrollTop}px`:l.value="-1.7rem"}else l.value="-1.7rem"};return _e(()=>{ie(()=>n.hash,i=>{if(s.value){const u=document.querySelector(`#toc a.toc-link[href$="${i}"]`);if(!u)return;const{top:d,height:p}=s.value.getBoundingClientRect(),{top:m,height:g}=u.getBoundingClientRect();md+p&&a(s.value.scrollTop+m+g-d-p)}}),ie(()=>n.fullPath,c,{flush:"post",immediate:!0})}),()=>{var u,d;const i=e.items.length?Wo(e.items,e.headerDepth):r.value.headers?Wo(r.value.headers,e.headerDepth):null;return i?f("div",{class:"toc-place-holder"},[f("aside",{id:"toc"},[(u=t.before)==null?void 0:u.call(t),f("div",{class:"toc-header"},[o.value.toc,f(ym)]),f("div",{class:"toc-wrapper",ref:s},[i,f("div",{class:"toc-marker",style:{top:l.value}})]),(d=t.after)==null?void 0:d.call(t)])]):null}}}),Sc=q({name:"SkipLink",props:{content:{type:String,default:"main-content"}},setup(e){const t=ge(),n=de(),r=Fe(),o=({target:s})=>{const l=document.querySelector(s.hash);if(l){const a=()=>{l.removeAttribute("tabindex"),l.removeEventListener("blur",a)};l.setAttribute("tabindex","-1"),l.addEventListener("blur",a),l.focus(),window.scrollTo(0,0)}};return _e(()=>{ie(()=>t.value.path,()=>r.value.focus())}),()=>[f("span",{ref:r,tabindex:"-1"}),f("a",{href:`#${e.content}`,class:"vp-skip-link sr-only",onClick:o},n.value.routeLocales.skipToContent)]}});let xo=null,Rn=null;const Em={wait:()=>xo,pending:()=>{xo=new Promise(e=>{Rn=e})},resolve:()=>{Rn==null||Rn(),xo=null,Rn=null}},Tc=()=>Em;var Cm=q({name:"FadeSlideY",slots:Object,setup(e,{slots:t}){const{resolve:n,pending:r}=Tc();return()=>f($t,{name:"fade-slide-y",mode:"out-in",onBeforeEnter:n,onBeforeLeave:r},()=>{var o;return(o=t.default)==null?void 0:o.call(t)})}});const xm=(e,t)=>{const n=e.replace(t,"/").split("/"),r=[];let o=ps(t);return n.forEach((s,l)=>{l!==n.length-1?(o+=`${s}/`,r.push({link:o,name:s||"Home"})):s!==""&&(o+=s,r.push({link:o,name:s}))}),r},kc=(e,{slots:t})=>{var d,p;const{bgImage:n,bgImageDark:r,bgImageStyle:o,color:s,description:l,image:a,imageDark:c,header:i,features:u=[]}=e;return f("div",{class:"vp-feature-wrapper"},[n?f("div",{class:["vp-feature-bg",{light:r}],style:[{"background-image":`url(${n})`},o]}):null,r?f("div",{class:"vp-feature-bg dark",style:[{"background-image":`url(${r})`},o]}):null,f("div",{class:"vp-feature",style:s?{color:s}:{}},[((d=t.image)==null?void 0:d.call(t,e))||[a?f("img",{class:["vp-feature-image",{light:c}],src:Ne(a),alt:""}):null,c?f("img",{class:"vp-feature-image dark",src:Ne(c),alt:""}):null],((p=t.info)==null?void 0:p.call(t,e))||[i?f("h2",{class:"vp-feature-header"},i):null,l?f("p",{class:"vp-feature-description",innerHTML:l}):null],u.length?f("div",{class:"vp-features"},u.map(({icon:m,title:g,details:E,link:w})=>{const b=[f("h3",{class:"vp-feature-title"},[f(De,{icon:m}),f("span",{innerHTML:g})]),f("p",{class:"vp-feature-details",innerHTML:E})];return w?mn(w)?f("a",{class:"vp-feature-item link",href:w,"aria-label":g,target:"_blank"},b):f(je,{class:"vp-feature-item link",to:w,"aria-label":g},()=>b):f("div",{class:"vp-feature-item"},b)})):null])])};kc.displayName="FeaturePanel";var Kl=kc,Sm=q({name:"HeroInfo",slots:Object,setup(e,{slots:t}){const n=Se(),r=gs(),o=k(()=>n.value.heroFullScreen??!1),s=k(()=>{const{heroText:i,tagline:u}=n.value;return{text:i??r.value.title??"Hello",tagline:u??r.value.description??"",isFullScreen:o.value}}),l=k(()=>{const{heroText:i,heroImage:u,heroImageDark:d,heroAlt:p,heroImageStyle:m}=n.value;return{image:u?Ne(u):null,imageDark:d?Ne(d):null,heroStyle:m,alt:p||i||"",isFullScreen:o.value}}),a=k(()=>{const{bgImage:i,bgImageDark:u,bgImageStyle:d}=n.value;return{image:xe(i)?Ne(i):null,imageDark:xe(u)?Ne(u):null,bgStyle:d,isFullScreen:o.value}}),c=k(()=>n.value.actions??[]);return()=>{var i,u,d;return f("header",{class:["vp-hero-info-wrapper",{fullscreen:o.value}]},[((i=t.heroBg)==null?void 0:i.call(t,a.value))||[a.value.image?f("div",{class:["vp-hero-mask",{light:a.value.imageDark}],style:[{"background-image":`url(${a.value.image})`},a.value.bgStyle]}):null,a.value.imageDark?f("div",{class:"vp-hero-mask dark",style:[{"background-image":`url(${a.value.imageDark})`},a.value.bgStyle]}):null],f("div",{class:"vp-hero-info"},[((u=t.heroImage)==null?void 0:u.call(t,l.value))||f(on,{appear:!0,type:"group"},()=>[l.value.image?f("img",{key:"light",class:["vp-hero-image",{light:l.value.imageDark}],style:l.value.heroStyle,src:l.value.image,alt:l.value.alt}):null,l.value.imageDark?f("img",{key:"dark",class:"vp-hero-image dark",style:l.value.heroStyle,src:l.value.imageDark,alt:l.value.alt}):null]),((d=t.heroInfo)==null?void 0:d.call(t,s.value))??f("div",{class:"vp-hero-infos"},[s.value.text?f(on,{appear:!0,delay:.04},()=>f("h1",{id:"main-title"},s.value.text)):null,s.value.tagline?f(on,{appear:!0,delay:.08},()=>f("p",{id:"main-description",innerHTML:s.value.tagline})):null,c.value.length?f(on,{appear:!0,delay:.12},()=>f("p",{class:"vp-hero-actions"},c.value.map(p=>f(Ve,{class:["vp-hero-action",p.type||"default"],config:p,noExternalLinkIcon:!0},p.icon?{before:()=>f(De,{icon:p.icon})}:{})))):null])])])}}});const Ac=(e,{slots:t})=>{var p,m,g;const{bgImage:n,bgImageDark:r,bgImageStyle:o,color:s,description:l,image:a,imageDark:c,header:i,highlights:u=[],type:d="un-order"}=e;return f("div",{class:"vp-highlight-wrapper",style:s?{color:s}:{}},[n?f("div",{class:["vp-highlight-bg",{light:r}],style:[{"background-image":`url(${n})`},o]}):null,r?f("div",{class:"vp-highlight-bg dark",style:[{"background-image":`url(${r})`},o]}):null,f("div",{class:"vp-highlight"},[((p=t.image)==null?void 0:p.call(t,e))||[a?f("img",{class:["vp-highlight-image",{light:c}],src:Ne(a),alt:""}):null,c?f("img",{class:"vp-highlight-image dark",src:Ne(c),alt:""}):null],((m=t.info)==null?void 0:m.call(t,e))||[f("div",{class:"vp-highlight-info-wrapper"},f("div",{class:"vp-highlight-info"},[i?f("h2",{class:"vp-highlight-header",innerHTML:i}):null,l?f("p",{class:"vp-highlight-description",innerHTML:l}):null,((g=t.highlights)==null?void 0:g.call(t,u))||f(d==="order"?"ol":d==="no-order"?"dl":"ul",{class:"vp-highlights"},u.map(({icon:E,title:w,details:b,link:S})=>{const y=[f(d==="no-order"?"dt":"h3",{class:"vp-highlight-title"},[E?f(De,{class:"vp-highlight-icon",icon:E}):null,f("span",{innerHTML:w})]),b?f(d==="no-order"?"dd":"p",{class:"vp-highlight-details",innerHTML:b}):null];return f(d==="no-order"?"div":"li",{class:["vp-highlight-item-wrapper",{link:S}]},S?mn(S)?f("a",{class:"vp-highlight-item link",href:S,"aria-label":w,target:"_blank"},y):f(je,{class:"vp-highlight-item link",to:S,"aria-label":w},()=>y):f("div",{class:"vp-highlight-item"},y))}))]))]])])};Ac.displayName="HighlightPanel";var Tm=Ac,km=q({name:"HomePage",slots:Object,setup(e,{slots:t}){const n=cr(),r=Se(),o=k(()=>{const{features:l}=r.value;return Ho(l)?l:null}),s=k(()=>{const{highlights:l}=r.value;return Ho(l)?l:null});return()=>{var l,a,c,i;return f("main",{id:"main-content",class:["vp-project-home ",{pure:n.value}],"aria-labelledby":r.value.heroText===null?"":"main-title"},[(l=t.top)==null?void 0:l.call(t),f(Sm),((a=s.value)==null?void 0:a.map(u=>"features"in u?f(Kl,u):f(Tm,u)))||(o.value?f(on,{appear:!0,delay:.24},()=>f(Kl,{features:o.value})):null),(c=t.center)==null?void 0:c.call(t),f(on,{appear:!0,delay:.32},()=>f(gc)),(i=t.bottom)==null?void 0:i.call(t)])}}}),Am=q({name:"BreadCrumb",setup(){const e=ge(),t=xn(),n=Se(),r=de(),o=Fe([]),s=k(()=>(n.value.breadcrumb||n.value.breadcrumb!==!1&&r.value.breadcrumb!==!1)&&o.value.length>1),l=k(()=>n.value.breadcrumbIcon||n.value.breadcrumbIcon!==!1&&r.value.breadcrumbIcon!==!1),a=()=>{const c=xm(e.value.path,t.value).map(({link:i,name:u})=>{const{path:d,meta:p}=Jr(i);return p?{title:p[mt.shortTitle]||p[mt.title]||u,icon:p[mt.icon],path:d}:null}).filter(i=>i!==null);c.length>1&&(o.value=c)};return _e(()=>{ie(()=>e.value.path,a,{immediate:!0})}),()=>f("nav",{class:["vp-breadcrumb",{disable:!s.value}]},s.value?f("ol",{vocab:"https://schema.org/",typeof:"BreadcrumbList"},o.value.map((c,i)=>f("li",{class:{"is-active":o.value.length-1===i},property:"itemListElement",typeof:"ListItem"},[f(je,{to:c.path,property:"item",typeof:"WebPage"},()=>[l.value?f(De,{icon:c.icon}):null,f("span",{property:"name"},c.title||"Unknown")]),f("meta",{property:"position",content:i+1})]))):[])}});const Yl=e=>e===!1||Gr(e)?e:xe(e)?fn(e,!0):null,Uo=(e,t,n)=>{const r=e.findIndex(o=>o.link===t);if(r!==-1){const o=e[r+n];return o!=null&&o.link?o:null}for(const o of e)if(o.children){const s=Uo(o.children,t,n);if(s)return s}return null};var Lm=q({name:"PageNav",setup(){const e=de(),t=Se(),n=ks(),r=ge(),o=Pv(),s=k(()=>{const a=Yl(t.value.prev);return a===!1?null:a||(e.value.prevLink===!1?null:Uo(n.value,r.value.path,-1))}),l=k(()=>{const a=Yl(t.value.next);return a===!1?null:a||(e.value.nextLink===!1?null:Uo(n.value,r.value.path,1))});return Pe("keydown",a=>{a.altKey&&(a.key==="ArrowRight"?l.value&&(o(l.value.link),a.preventDefault()):a.key==="ArrowLeft"&&s.value&&(o(s.value.link),a.preventDefault()))}),()=>s.value||l.value?f("nav",{class:"vp-page-nav"},[s.value?f(Ve,{class:"prev",config:s.value},()=>{var a,c;return[f("div",{class:"hint"},[f("span",{class:"arrow start"}),e.value.metaLocales.prev]),f("div",{class:"link"},[f(De,{icon:(a=s.value)==null?void 0:a.icon}),(c=s.value)==null?void 0:c.text])]}):null,l.value?f(Ve,{class:"next",config:l.value},()=>{var a,c;return[f("div",{class:"hint"},[e.value.metaLocales.next,f("span",{class:"arrow end"})]),f("div",{class:"link"},[(a=l.value)==null?void 0:a.text,f(De,{icon:(c=l.value)==null?void 0:c.icon})])]}):null]):null}});const Rm={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},Im=({docsRepo:e,docsBranch:t,docsDir:n,filePathRelative:r,editLinkPattern:o})=>{if(!r)return null;const s=Ai(e);let l;return o?l=o:s!==null&&(l=Rm[s]),l?l.replace(/:repo/u,Xt(e)?e:`https://github.com/${e}`).replace(/:branch/u,t).replace(/:path/u,ri(`${ps(n)}/${r}`)):null},Pm=()=>{const e=de(),t=ge(),n=Se();return k(()=>{const{repo:r,docsRepo:o=r,docsBranch:s="main",docsDir:l="",editLink:a,editLinkPattern:c=""}=e.value;if(!(n.value.editLink??a??!0)||!o)return null;const i=Im({docsRepo:o,docsBranch:s,docsDir:l,editLinkPattern:c,filePathRelative:t.value.filePathRelative});return i?{text:e.value.metaLocales.editLink,link:i}:null})},Om=()=>{const e=gs(),t=de(),n=ge(),r=Se();return k(()=>{var o,s;return!(r.value.lastUpdated??t.value.lastUpdated??!0)||!((o=n.value.git)!=null&&o.updatedTime)?null:new Date((s=n.value.git)==null?void 0:s.updatedTime).toLocaleString(e.value.lang)})},Mm=()=>{const e=de(),t=ge(),n=Se();return k(()=>{var r;return n.value.contributors??e.value.contributors??!0?((r=t.value.git)==null?void 0:r.contributors)??null:null})};var $m=q({name:"PageTitle",setup(){const e=ge(),t=Se(),n=de(),{info:r,items:o}=Nv();return()=>f("div",{class:"vp-page-title"},[f("h1",[n.value.titleIcon===!1?null:f(De,{icon:t.value.icon}),e.value.title]),f(bm,{info:r.value,...o.value===null?{}:{items:o.value}}),f("hr")])}});const Lc=()=>f(Ee,{name:"edit"},()=>[f("path",{d:"M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"}),f("path",{d:"M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"})]);Lc.displayName="EditIcon";var Nm=q({name:"PageMeta",setup(){const e=de(),t=Pm(),n=Om(),r=Mm();return()=>{const{metaLocales:o}=e.value;return f("footer",{class:"page-meta"},[t.value?f("div",{class:"meta-item edit-link"},f(Ve,{class:"label",config:t.value},{before:()=>f(Lc)})):null,f("div",{class:"meta-item git-info"},[n.value?f("div",{class:"update-time"},[f("span",{class:"label"},`${o.lastUpdated}: `),f(Qr,()=>f("span",{class:"info"},n.value))]):null,r.value&&r.value.length?f("div",{class:"contributors"},[f("span",{class:"label"},`${o.contributors}: `),r.value.map(({email:s,name:l},a)=>[f("span",{class:"contributor",title:`email: ${s}`},l),a!==r.value.length-1?",":""])]):null])])}}}),Dm=q({name:"NormalPage",slots:Object,setup(e,{slots:t}){const n=Se(),{isDarkmode:r}=ur(),o=de(),s=k(()=>n.value.toc||n.value.toc!==!1&&o.value.toc!==!1);return()=>f("main",{id:"main-content",class:"vp-page"},f(ot("LocalEncrypt")?rt("LocalEncrypt"):yi,()=>{var l,a,c,i;return[(l=t.top)==null?void 0:l.call(t),n.value.cover?f("div",{class:"page-cover"},f("img",{src:Ne(n.value.cover),alt:"","no-view":""})):null,f(Am),f($m),s.value?f(wm,{headerDepth:n.value.headerDepth??o.value.headerDepth??2},{before:()=>{var u;return(u=t.tocBefore)==null?void 0:u.call(t)},after:()=>{var u;return(u=t.tocAfter)==null?void 0:u.call(t)}}):null,(a=t.contentBefore)==null?void 0:a.call(t),f(gc),(c=t.contentAfter)==null?void 0:c.call(t),f(Nm),f(Lm),ot("CommentService")?f(rt("CommentService"),{darkmode:r.value}):null,(i=t.bottom)==null?void 0:i.call(t)]}))}}),Fm=q({name:"Layout",slots:Object,setup(e,{slots:t}){de();const n=ge(),r=Se(),{isMobile:o}=Zr(),s=k(()=>"none");return()=>[f(Sc),f(mc,{},{default:()=>{var l;return((l=t.default)==null?void 0:l.call(t))||(r.value.home?f(km):f(Cm,()=>f(Dm,{key:n.value.path},{top:()=>{var a;return(a=t.top)==null?void 0:a.call(t)},bottom:()=>{var a;return(a=t.bottom)==null?void 0:a.call(t)},contentBefore:()=>{var a;return(a=t.contentBefore)==null?void 0:a.call(t)},contentAfter:()=>{var a;return(a=t.contentAfter)==null?void 0:a.call(t)},tocBefore:()=>{var a;return(a=t.tocBefore)==null?void 0:a.call(t)},tocAfter:()=>{var a;return(a=t.tocAfter)==null?void 0:a.call(t)}})))},...s.value==="none"?{}:{navScreenBottom:()=>f(rt("BloggerInfo"))},...!o.value&&s.value==="always"?{sidebar:()=>f(rt("BloggerInfo"))}:{}})]}}),Hm=q({name:"NotFoundHint",setup(){const e=de(),t=()=>{const n=e.value.routeLocales.notFoundMsg;return n[Math.floor(Math.random()*n.length)]};return()=>f("div",{class:"not-found-hint"},[f("p",{class:"error-code"},"404"),f("h1",{class:"error-title"},e.value.routeLocales.notFoundTitle),f("p",{class:"error-hint"},t())])}}),Bm=q({name:"NotFound",slots:Object,setup(e,{slots:t}){const n=Dt(),r=xn(),o=de();return()=>[f(Sc),f(mc,{noSidebar:!0},()=>{var s;return f("main",{id:"main-content",class:"vp-page not-found"},((s=t.default)==null?void 0:s.call(t))||[f(Hm),f("div",{class:"actions"},[f("button",{type:"button",class:"action-button",onClick:()=>{window.history.go(-1)}},o.value.routeLocales.back),f("button",{type:"button",class:"action-button",onClick:()=>{n.push(o.value.home??r.value)}},o.value.routeLocales.home)])])})]}});Ah(e=>{const t=e.t,n=e.I!==!1,r=e.i;return n?{title:t,content:r?()=>[f(De,{icon:r}),t]:null,order:e.O,index:e.I}:null});const jm=lt({enhance:({app:e,router:t})=>{const{scrollBehavior:n}=t.options;t.options.scrollBehavior=async(...r)=>(await Tc().wait(),n(...r)),Hv(e),e.component("HopeIcon",De)},setup:()=>{Bv(),Wv()},layouts:{Layout:Fm,NotFound:Bm}}),Tr=[Np,wh,kh,Oh,Nh,Bh,Wh,Yh,lv,fv,Sv,jm],Vm=JSON.parse('{"base":"/","lang":"en-US","title":"Decentralized Transport Protocol","description":"Adds Web3 features to existing Web2 data transfer apps","head":[],"locales":{}}');var Pn=Fe(Vm),zm=Vd,Wm=()=>{const e=Tp({history:zm(ps("/")),routes:[{name:"vuepress-route",path:"/:catchAll(.*)",components:{}}],scrollBehavior:(t,n,r)=>r||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,n)=>{if(t.path!==n.path||n===vt){const r=Jr(t.path);if(r.path!==t.path)return r.path;const o=await r.loader();t.meta={...r.meta,_pageChunk:o}}}),e},Um=e=>{e.component("ClientOnly",Qr),e.component("Content",bi),e.component("RouteLink",je)},qm=(e,t,n)=>{const r=k(()=>t.currentRoute.value.path),o=_s(r,()=>t.currentRoute.value.meta._pageChunk),s=k(()=>jt.resolveLayouts(n)),l=k(()=>jt.resolveRouteLocale(Pn.value.locales,r.value)),a=k(()=>jt.resolveSiteLocaleData(Pn.value,l.value)),c=k(()=>o.value.comp),i=k(()=>o.value.data),u=k(()=>i.value.frontmatter),d=k(()=>jt.resolvePageHeadTitle(i.value,a.value)),p=k(()=>jt.resolvePageHead(d.value,u.value,a.value)),m=k(()=>jt.resolvePageLang(i.value,a.value)),g=k(()=>jt.resolvePageLayout(i.value,s.value)),E={layouts:s,pageData:i,pageComponent:c,pageFrontmatter:u,pageHead:p,pageHeadTitle:d,pageLang:m,pageLayout:g,redirects:mi,routeLocale:l,routePath:r,routes:Yn,siteData:Pn,siteLocaleData:a};return e.provide(ms,E),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>u.value},$head:{get:()=>p.value},$headTitle:{get:()=>d.value},$lang:{get:()=>m.value},$page:{get:()=>i.value},$routeLocale:{get:()=>l.value},$site:{get:()=>Pn.value},$siteLocale:{get:()=>a.value},$withBase:{get:()=>Ne}}),E},Gm=()=>{const e=Lp(),t=hi();let n=[];const r=()=>{e.value.forEach(l=>{const a=Km(l);a&&n.push(a)})},o=()=>{const l=[];return e.value.forEach(a=>{const c=Ym(a);c&&l.push(c)}),l},s=()=>{document.documentElement.lang=t.value;const l=o();n.forEach((a,c)=>{const i=l.findIndex(u=>a.isEqualNode(u));i===-1?(a.remove(),delete n[c]):l.splice(i,1)}),l.forEach(a=>document.head.appendChild(a)),n=[...n.filter(a=>!!a),...l]};un(Pp,s),_e(()=>{r(),ie(e,s,{immediate:!1})})},Km=([e,t,n=""])=>{const r=Object.entries(t).map(([a,c])=>xe(c)?`[${a}=${JSON.stringify(c)}]`:c===!0?`[${a}]`:"").join(""),o=`head > ${e}${r}`;return Array.from(document.querySelectorAll(o)).find(a=>a.innerText===n)||null},Ym=([e,t,n])=>{if(!xe(e))return null;const r=document.createElement(e);return Gr(t)&&Object.entries(t).forEach(([o,s])=>{xe(s)?r.setAttribute(o,s):s===!0&&r.setAttribute(o,"")}),xe(n)&&r.appendChild(document.createTextNode(n)),r},Jm=ud,Qm=async()=>{var n;const e=Jm({name:"Vuepress",setup(){var s;Gm();for(const l of Tr)(s=l.setup)==null||s.call(l);const r=Tr.flatMap(({rootComponents:l=[]})=>l.map(a=>f(a))),o=Rp();return()=>[f(o.value),r]}}),t=Wm();Um(e),qm(e,t,Tr);for(const r of Tr)await((n=r.enhance)==null?void 0:n.call(r,{app:e,router:t,siteData:Pn}));return e.use(t),{app:e,router:t}};Qm().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{Wa as a,Ua as b,Zm as c,Qm as createVueApp,Ce as d,eg as e,Xm as o,rt as r,Au as w}; +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = ["assets/index.html-BSnE9a5s.js","assets/plugin-vue_export-helper-DlAUqK2U.js","assets/faq.html-B9wOlu7B.js","assets/intro.html-DJw2Nump.js","assets/index.html-K9gGP3vT.js","assets/editors.html-DwjnlUpI.js","assets/index.html-xbvo-U6r.js","assets/rpc_firewall.html-C8sUbYFf.js","assets/web3_rust.html-D5SN0Dc_.js","assets/index.html-BbkzL85r.js","assets/api_rust.html-jEWBwXo5.js","assets/api_typescript.html-C6Hyg1mu.js","assets/design.html-BzmiLaM4.js","assets/ref_broadcast-Cg4jrlCe.js","assets/future_work.html-BqJ-TElc.js","assets/p2p_broadcast-DKREXEsi.js","assets/scripts.html-D_w4s9EQ.js","assets/full_setup.html-CCMysVzO.js","assets/install.html-BizGowkj.js","assets/npm_only.html-Bs9x0lRw.js","assets/runtime_only.html-BsGx0Xbr.js","assets/index.html-2JbiJiHq.js","assets/api_rust.html-BxLNqA0i.js","assets/api_typescript.html-DpDyABcd.js","assets/design.html-BCNdCdft.js","assets/future_work.html-iK8jJpLI.js","assets/scripts.html-Cae6ml7k.js","assets/404.html-B7K0IBbl.js","assets/index.html-By-UCih8.js"] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} diff --git a/assets/design.html-BCNdCdft.js b/assets/design.html-BCNdCdft.js new file mode 100644 index 0000000..c8960a1 --- /dev/null +++ b/assets/design.html-BCNdCdft.js @@ -0,0 +1 @@ +import{_ as r,a as l,b as c,c as d,d as h,e as p,f as u}from"./ref_broadcast-Cg4jrlCe.js";import{_ as g}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as o,o as m,c as f,a as e,b as t,d as a,w as b,e as n}from"./app-DlOHg9Xr.js";const v={},y=e("h2",{id:"target-audience",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#target-audience"},[e("span",null,"Target Audience")])],-1),w=e("p",null,"Developers should first read the API they intend to use.",-1),_=e("p",null,"This document is for developers curious about DTP inner works.",-1),T=e("h2",{id:"at-high-level-how-is-the-sui-network-used",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#at-high-level-how-is-the-sui-network-used"},[e("span",null,"At high level, how is the Sui Network used?")])],-1),k={href:"https://docs.sui.io/devnet/learn/how-sui-works#simple-transactions",target:"_blank",rel:"noopener noreferrer"},S=n('

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data "exit" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be "observed" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most "control plane" synchronizations.

DTP Glossary

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

',9),x=e("strong",null,"Objects:",-1),P={href:"https://docs.sui.io/build/programming-with-objects",target:"_blank",rel:"noopener noreferrer"},D=n('

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be "sent data can be deleted from network storage after 48 hours (2 epochs)". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

Firewall

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

Multi-Channel Connection

Media byte streams are ineviteably divided into transaction "block" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

',20),j={href:"https://docs.google.com/spreadsheets/d/1zBrB1ifhPpnLlsDr6nBN_N55Kkw9hX06a7EVUpogyn4/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"},A=n('

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

High-Availability and Load Balancing

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should "pull it".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

Uni-directional Transfer

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

Public Broadcasting

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic "on air" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).
',16);function q(z,L){const i=o("ExternalLinkIcon"),s=o("RouteLink");return m(),f("div",null,[y,w,_,T,e("p",null,[t("Sui owned objects are used for unidirectional data transfer with sub-second latency (See "),e("a",k,[t("Simple Transaction"),a(i)]),t(" in Sui docs).")]),S,e("p",null,[x,t(" Usually refer to Sui objects (See "),e("a",P,[t("Sui Docs"),a(i)]),t(")")]),D,e("p",null,[t("Some estimations (See on "),e("a",j,[t("Google Sheet"),a(i)]),t("):")]),A,e("p",null,[t("There are also some technical challenges particular to broadcasting (See "),a(s,{to:"/ref/future_work.html#broadcasting-challenges"},{default:b(()=>[t("Future Work")]),_:1}),t(").")])])}const O=g(v,[["render",q],["__file","design.html.vue"]]),I=JSON.parse('{"path":"/ref/design.html","title":"Design","lang":"en-US","frontmatter":{"title":"Design","contributors":true,"editLink":true,"headerDepth":0,"description":"Target Audience Developers should first read the API they intend to use. This document is for developers curious about DTP inner works. At high level, how is the Sui Network use...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/ref/design.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Design"}],["meta",{"property":"og:description","content":"Target Audience Developers should first read the API they intend to use. This document is for developers curious about DTP inner works. At high level, how is the Sui Network use..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://dtp.dev/assets/images/design_terms.png?url"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Design"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Design\\",\\"image\\":[\\"https://dtp.dev/assets/images/design_terms.png?url\\",\\"https://dtp.dev/assets/images/ref_firewall.png?url\\",\\"https://dtp.dev/assets/images/multi_channels.png?url\\",\\"https://dtp.dev/assets/images/multi_channel_est.png?url\\",\\"https://dtp.dev/assets/images/ref_ha.png?url\\",\\"https://dtp.dev/assets/images/ref_uni.png?url\\",\\"https://dtp.dev/assets/images/ref_broadcast.png?url\\"],\\"dateModified\\":null,\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Target Audience","slug":"target-audience","link":"#target-audience","children":[]},{"level":2,"title":"At high level, how is the Sui Network used?","slug":"at-high-level-how-is-the-sui-network-used","link":"#at-high-level-how-is-the-sui-network-used","children":[]},{"level":2,"title":"DTP Glossary","slug":"dtp-glossary","link":"#dtp-glossary","children":[]},{"level":2,"title":"Firewall","slug":"firewall","link":"#firewall","children":[]},{"level":2,"title":"Multi-Channel Connection","slug":"multi-channel-connection","link":"#multi-channel-connection","children":[]},{"level":2,"title":"High-Availability and Load Balancing","slug":"high-availability-and-load-balancing","link":"#high-availability-and-load-balancing","children":[]},{"level":2,"title":"Uni-directional Transfer","slug":"uni-directional-transfer","link":"#uni-directional-transfer","children":[]},{"level":2,"title":"Public Broadcasting","slug":"public-broadcasting","link":"#public-broadcasting","children":[]}],"git":{"createdTime":null,"updatedTime":null,"contributors":[]},"readingTime":{"minutes":4.12,"words":1235},"filePathRelative":"ref/design.md","autoDesc":true}');export{O as comp,I as data}; diff --git a/assets/design.html-BzmiLaM4.js b/assets/design.html-BzmiLaM4.js new file mode 100644 index 0000000..f71de6f --- /dev/null +++ b/assets/design.html-BzmiLaM4.js @@ -0,0 +1 @@ +import{_ as r,a as l,b as c,c as d,d as h,e as p,f as u}from"./ref_broadcast-Cg4jrlCe.js";import{_ as g}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as o,o as m,c as f,a as e,b as t,d as a,w as b,e as n}from"./app-DlOHg9Xr.js";const y={},v=e("h2",{id:"target-audience",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#target-audience"},[e("span",null,"Target Audience")])],-1),w=e("p",null,"Developers should first read the API they intend to use.",-1),_=e("p",null,"This document is for developers curious about DTP inner works.",-1),T=e("h2",{id:"at-high-level-how-is-the-sui-network-used",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#at-high-level-how-is-the-sui-network-used"},[e("span",null,"At high level, how is the Sui Network used?")])],-1),k={href:"https://docs.sui.io/devnet/learn/how-sui-works#simple-transactions",target:"_blank",rel:"noopener noreferrer"},S=n('

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data "exit" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be "observed" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most "control plane" synchronizations.

DTP Glossary

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

',9),x=e("strong",null,"Objects:",-1),P={href:"https://docs.sui.io/build/programming-with-objects",target:"_blank",rel:"noopener noreferrer"},D=n('

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be "sent data can be deleted from network storage after 48 hours (2 epochs)". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

Firewall

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

Multi-Channel Connection

Media byte streams are ineviteably divided into transaction "block" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

',20),j={href:"https://docs.google.com/spreadsheets/d/1zBrB1ifhPpnLlsDr6nBN_N55Kkw9hX06a7EVUpogyn4/edit?usp=sharing",target:"_blank",rel:"noopener noreferrer"},A=n('

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

High-Availability and Load Balancing

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should "pull it".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

Uni-directional Transfer

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

Public Broadcasting

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic "on air" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).
',16);function q(z,L){const i=o("ExternalLinkIcon"),s=o("RouteLink");return m(),f("div",null,[v,w,_,T,e("p",null,[t("Sui owned objects are used for unidirectional data transfer with sub-second latency (See "),e("a",k,[t("Simple Transaction"),a(i)]),t(" in Sui docs).")]),S,e("p",null,[x,t(" Usually refer to Sui objects (See "),e("a",P,[t("Sui Docs"),a(i)]),t(")")]),D,e("p",null,[t("Some estimations (See on "),e("a",j,[t("Google Sheet"),a(i)]),t("):")]),A,e("p",null,[t("There are also some technical challenges particular to broadcasting (See "),a(s,{to:"/docs/future_work.html#broadcasting-challenges"},{default:b(()=>[t("Future Work")]),_:1}),t(").")])])}const O=g(y,[["render",q],["__file","design.html.vue"]]),I=JSON.parse('{"path":"/docs/design.html","title":"Design","lang":"en-US","frontmatter":{"title":"Design","contributors":true,"editLink":true,"headerDepth":0,"description":"Target Audience Developers should first read the API they intend to use. This document is for developers curious about DTP inner works. At high level, how is the Sui Network use...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/docs/design.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Design"}],["meta",{"property":"og:description","content":"Target Audience Developers should first read the API they intend to use. This document is for developers curious about DTP inner works. At high level, how is the Sui Network use..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://dtp.dev/assets/images/design_terms.png?url"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Design"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Design\\",\\"image\\":[\\"https://dtp.dev/assets/images/design_terms.png?url\\",\\"https://dtp.dev/assets/images/ref_firewall.png?url\\",\\"https://dtp.dev/assets/images/multi_channels.png?url\\",\\"https://dtp.dev/assets/images/multi_channel_est.png?url\\",\\"https://dtp.dev/assets/images/ref_ha.png?url\\",\\"https://dtp.dev/assets/images/ref_uni.png?url\\",\\"https://dtp.dev/assets/images/ref_broadcast.png?url\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Target Audience","slug":"target-audience","link":"#target-audience","children":[]},{"level":2,"title":"At high level, how is the Sui Network used?","slug":"at-high-level-how-is-the-sui-network-used","link":"#at-high-level-how-is-the-sui-network-used","children":[]},{"level":2,"title":"DTP Glossary","slug":"dtp-glossary","link":"#dtp-glossary","children":[]},{"level":2,"title":"Firewall","slug":"firewall","link":"#firewall","children":[]},{"level":2,"title":"Multi-Channel Connection","slug":"multi-channel-connection","link":"#multi-channel-connection","children":[]},{"level":2,"title":"High-Availability and Load Balancing","slug":"high-availability-and-load-balancing","link":"#high-availability-and-load-balancing","children":[]},{"level":2,"title":"Uni-directional Transfer","slug":"uni-directional-transfer","link":"#uni-directional-transfer","children":[]},{"level":2,"title":"Public Broadcasting","slug":"public-broadcasting","link":"#public-broadcasting","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":4.12,"words":1235},"filePathRelative":"docs/design.md","localizedDate":"February 14, 2024","autoDesc":true}');export{O as comp,I as data}; diff --git a/assets/editors.html-DwjnlUpI.js b/assets/editors.html-DwjnlUpI.js new file mode 100644 index 0000000..57d90bc --- /dev/null +++ b/assets/editors.html-DwjnlUpI.js @@ -0,0 +1,7 @@ +import{_ as i}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as s,o as r,c as d,a as t,b as e,d as o,e as a}from"./app-DlOHg9Xr.js";const c="/assets/images/propose-change.png",l={},p=t("p",null,"Anyone with a Github account can participate.",-1),h={href:"https://github.com/chainmovers/dtp/tree/main/docs",target:"_blank",rel:"noopener noreferrer"},u=a('

Open the editor with the "Edit this pages on Github" link at the bottom.

When ready to propose your changes just select "Create a new branch" and give it a name:
Propose Changes

Your proposed changes will be merged after review.

Editing the website on your machine (advanced contributors)

If you prefer to preview exactly your change, then you need to run vuepress on your machine and modify the markdown files with an editor (e.g. VSCode).

Prerequisites:

',7),m={href:"https://nodejs.dev/en/learn/how-to-install-nodejs/",target:"_blank",rel:"noopener noreferrer"},g={href:"https://pnpm.io/installation",target:"_blank",rel:"noopener noreferrer"},b={href:"https://dtp.dev/how-to/install",target:"_blank",rel:"noopener noreferrer"},f=a(`

For the one-time vuepress installation do:

$ cd ~/suibase/workdirs/common/extensions/dtp/docs
+$ pnpm install
+

To start vuepress (the server) do:

$ cd ~/suibase/workdirs/common/extensions/dtp/docs
+$ pnpm start
+...
+Open your browser at http://localhost:8080
+

The browser updates as you change files under docs/src

`,5),v={href:"https://theme-hope.vuejs.press/guide/",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,"Submit your changes as a pull request, just ask as needed (not as hard as it seems once you do it once).",-1);function _(w,k){const n=s("ExternalLinkIcon");return r(),d("div",null,[p,t("p",null,[e("The website is built from markdown files (.md) and served directly from "),t("a",h,[e("github"),o(n)]),e(".")]),u,t("ul",null,[t("li",null,[e("NodeJS (>= 16.4) ( "),t("a",m,[e("https://nodejs.dev/en/learn/how-to-install-nodejs/"),o(n)]),e(" )")]),t("li",null,[e("pnpm ( "),t("a",g,[e("https://pnpm.io/installation"),o(n)]),e(" )")]),t("li",null,[e("DTP and Suibase ( "),t("a",b,[e("https://dtp.dev/how-to/install"),o(n)]),e(" )")])]),f,t("p",null,[e("See "),t("a",v,[e("https://theme-hope.vuejs.press/guide/"),o(n)]),e(" for advanced markdown features.")]),y])}const T=i(l,[["render",_],["__file","editors.html.vue"]]),E=JSON.parse('{"path":"/community/editors.html","title":"How to propose fix/change to the website?","lang":"en-US","frontmatter":{"title":"How to propose fix/change to the website?","order":2,"headerDepth":0,"contributors":true,"editLink":true,"description":"Anyone with a Github account can participate. The website is built from markdown files (.md) and served directly from github. Editing on Github (recommended for easy/quick chang...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/community/editors.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"How to propose fix/change to the website?"}],["meta",{"property":"og:description","content":"Anyone with a Github account can participate. The website is built from markdown files (.md) and served directly from github. Editing on Github (recommended for easy/quick chang..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"How to propose fix/change to the website?\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Editing on Github (recommended for easy/quick changes)","slug":"editing-on-github-recommended-for-easy-quick-changes","link":"#editing-on-github-recommended-for-easy-quick-changes","children":[]},{"level":2,"title":"Editing the website on your machine (advanced contributors)","slug":"editing-the-website-on-your-machine-advanced-contributors","link":"#editing-the-website-on-your-machine-advanced-contributors","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.77,"words":232},"filePathRelative":"community/editors.md","localizedDate":"February 14, 2024","autoDesc":true}');export{T as comp,E as data}; diff --git a/assets/faq.html-B9wOlu7B.js b/assets/faq.html-B9wOlu7B.js new file mode 100644 index 0000000..df40e5a --- /dev/null +++ b/assets/faq.html-B9wOlu7B.js @@ -0,0 +1 @@ +import{_ as c}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as i,o as p,c as l,a as e,b as t,d as n,w as s,e as r}from"./app-DlOHg9Xr.js";const d={},h=r('

FAQ

In one sentence... What can DTP do?

It is a TCP-Like protocol facilitating data transfer between web2 applications, with additional Web3 features such as services monetization, anonymity and security.

Can DTP be used between Web3 apps?

DTP can selectively connect front-ends WebApp to each other, while keeping the data transfer under the control of a dApps (transit on the Sui network).

As an example, you can use it to allow gamers safely exchange encrypted messages among themselves while they are on the same team in a Web3 game. In this case, DTP provides the WebApp to WebApp connectivity without making the players IP addresses visible.

What sort of data can DTP transport?

Any protocol, any data stream.

',8),m=r('

Can DTP be used with commercial application?

Yes. DTP is open-source and can freely be used in commercial application (Apache 2.0 License).

How much does it cost to use DTP?

Only the Sui gas needed to run it, expect the execution cost to be mostly driven by the number of bytes transferred.

There is no developer fee or middlemen commission collected for using DTP.

When will DTP have token?

Never.

dApps built on top of DTP can use tokens or charge additional Mist, but this is not within the scope of DTP itself.

Can DTP simply tunnel standard TCP, UDP, IP packets?

Transparent packets tunneling could be done, but it is not recommended.

DTP/Sui provides already reliable and ordered data transport. That would be redundant with say, what TCP would try to achieve within a tunnel.

',11),u=e("p",null,[e("strong",null,"Any plan to support another blockchain?")],-1),f=e("p",null,"No, unless a breakthrough in performance is possible with another blockchain architecture.",-1),b=e("p",null,"Sui provides stable time to finality (low jitter), parallelism and scalability (no contention between connections).",-1),g=e("p",null,"Low jitter allows small and predictable buffer size at the receivers.",-1),y=e("p",null,"Sui simple transactions makes sub-second streaming latency possible.",-1),_=e("p",null,"For now, DTP/Sui might not be well-suited for application that depends on fast sequence of query/response (since that requires two transactions finality). DTP attempts to minimize roundtrips and protocol handshakes at every step.",-1),w=e("p",null,[e("strong",null,"Where is the code?")],-1),T={href:"https://github.com/mario4tier/dtp",target:"_blank",rel:"noopener noreferrer"},v=e("p",null,[e("strong",null,"Where can I go for more questions?")],-1),P={href:"https://discord.gg/Erb6SwsVbH",target:"_blank",rel:"noopener noreferrer"};function k(D,A){const o=i("RouteLink"),a=i("ExternalLinkIcon");return p(),l("div",null,[h,e("p",null,[t("Data can be a few bytes for a one time secret exchange for authentication/login. At another extreme, the bandwidth can be for as much as an encrypted video stream (through the innovative combination of "),n(o,{to:"/docs/design.html#multi-channel-connection"},{default:s(()=>[t("DTP Multi-channels")]),_:1}),t(" and Sui network simple transactions). The economic feasibility of HD video streaming on blockchain is an open question...")]),m,e("p",null,[t("Instead, look into "),n(o,{to:"/how-to/install.html#choice-1-of-3-simplified-dtp-services-deployment"},{default:s(()=>[t("DTP Services Daemon")]),_:1}),t(" to efficiently terminate/bridge standard IP protocols. That eliminates protocol redundancy and better leverage what the Sui network already provide.")]),u,f,b,g,y,_,w,e("p",null,[t("DTP still in early design phase and is not yet release. See "),e("a",T,[t("GitHub"),n(a)]),t(' development branches for "work-in-progress".')]),v,e("p",null,[t("Try the Discord channel: "),e("a",P,[t("https://discord.gg/Erb6SwsVbH"),n(a)])])])}const I=c(d,[["render",k],["__file","faq.html.vue"]]),W=JSON.parse('{"path":"/faq.html","title":"FAQ","lang":"en-US","frontmatter":{"editLink":true,"description":"FAQ In one sentence... What can DTP do? It is a TCP-Like protocol facilitating data transfer between web2 applications, with additional Web3 features such as services monetizati...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/faq.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"FAQ"}],["meta",{"property":"og:description","content":"FAQ In one sentence... What can DTP do? It is a TCP-Like protocol facilitating data transfer between web2 applications, with additional Web3 features such as services monetizati..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"FAQ\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.62,"words":487},"filePathRelative":"faq.md","localizedDate":"February 14, 2024","autoDesc":true}');export{I as comp,W as data}; diff --git a/assets/images/favicon.png b/assets/favicon.png old mode 100644 new mode 100755 similarity index 100% rename from assets/images/favicon.png rename to assets/favicon.png diff --git a/assets/full_setup.html-CCMysVzO.js b/assets/full_setup.html-CCMysVzO.js new file mode 100644 index 0000000..269fefb --- /dev/null +++ b/assets/full_setup.html-CCMysVzO.js @@ -0,0 +1,38 @@ +import{_ as l}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as a,o as s,c as o,a as e,b as n,d as i,e as d}from"./app-DlOHg9Xr.js";const r={},c=e("h1",{id:"rust-development-setup-installation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#rust-development-setup-installation"},[e("span",null,"Rust Development Setup Installation")])],-1),u=e("h3",{id:"follow-the-sui-installation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#follow-the-sui-installation"},[e("span",null,"Follow the Sui installation")])],-1),p={href:"https://docs.sui.io/build/install#prerequisites",target:"_blank",rel:"noopener noreferrer"},m=e("h3",{id:"clone-dtp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#clone-dtp"},[e("span",null,"Clone DTP")])],-1),h={href:"https://github.com/mario4tier/dtp",target:"_blank",rel:"noopener noreferrer"},v=d(`

Initialize localnet

Just run the DTP "init-localnet" and it will initialize the whole DTP setup and (re)start the "sui" localnet process as needed.

The localnet will be re-initialized with always the same configuration, address and funding. (it uses its own configuration file at genesis for a deterministic setup).

From this point use "lsui" and "dsui" shell scripts (as a direct replacement of "sui") to access localnet and devnet respectively.

Output example:

~/dtp$ ./dtp/script/init-localnet
+Output location = /home/user/dtp-dev
+Stopping running localnet (sui process pid 1317)
+Building localnet using latest Sui devnet branch...
+    Finished dev [unoptimized + debuginfo] target(s) in 1.29s
+Removing existing /home/user/dtp-dev/localnet directory
+Starting new localnet process (may take up to 30 secs)
+.........
+New localnet started (sui 0.20.0, process pid 6798)
+========
+localnet => http://0.0.0.0:9000 (active)
+devnet => https://fullnode.devnet.sui.io:443
+========
+All addresses with coins:
+Showing 5 results.
+0x267d4904898cbc15f165a18541154ec8c5732fcb
+0x68db58b41d97e4cf1ea7d9327036ebd306a7930a
+0x99d821380348ee02dd685a3af6d7123d92db0d3c
+0xbbd8d0695c369b04e9207fca4ef9f5f15b2c0de7
+0xe7f134729591f52cf0638c2500a7ed228033a9e7
+========
+All coins owned by 0xe7f134729591f52cf0638c2500a7ed228033a9e7 (active):
+                 Object ID                  |  Gas Value
+----------------------------------------------------------------------
+ 0x0b162ef4f83118cc0ad811de35ed330ec3441d7b | 100000000000000
+ 0x2d43245a6af1f65847f7c18d5f6aabbd8e11299b | 100000000000000
+ 0x9811c29f1dadb67aadcd59c75693b4a91b347fbb | 100000000000000
+ 0xc8381677d3c213f9b0e9ef3d2d14051458b6af8a | 100000000000000
+ 0xd0b2b2227244707bce233d13bf537af7a6710c01 | 100000000000000
+========
+
+Remember:
+  Use "dsui" to access devnet
+  Use "lsui" to access your localnet
+
+Success. Try it by typing "lsui client gas"
+host:~/$
+

Publish DTP Package (localnet)

~/dtp$ publish-localnet

Run DTP Integration Test (localnet)

~/dtp$ cargo test

When running integration tests, the test setup makes sure a localnet (sui process) and a peer DTP service Daemon (dtp process) simulate interacting with a remote peer.

This allows to automate your own client/server integration test of your own application on a single machine (Just need to make sure to use a different set of object coin, client address and localhost:port. More on this later).

`,12);function b(f,g){const t=a("ExternalLinkIcon");return s(),o("div",null,[c,u,e("p",null,[e("a",p,[n("https://docs.sui.io/build/install#prerequisites"),i(t)])]),m,e("p",null,[e("a",h,[n("https://github.com/mario4tier/dtp"),i(t)])]),v])}const w=l(r,[["render",b],["__file","full_setup.html.vue"]]),y=JSON.parse('{"path":"/how-to/full_setup.html","title":"Rust Development Setup Installation","lang":"en-US","frontmatter":{"editLink":true,"description":"Rust Development Setup Installation Follow the Sui installation https://docs.sui.io/build/install#prerequisites Clone DTP https://github.com/mario4tier/dtp Initialize localnet J...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/how-to/full_setup.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Rust Development Setup Installation"}],["meta",{"property":"og:description","content":"Rust Development Setup Installation Follow the Sui installation https://docs.sui.io/build/install#prerequisites Clone DTP https://github.com/mario4tier/dtp Initialize localnet J..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Rust Development Setup Installation\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":3,"title":"Follow the Sui installation","slug":"follow-the-sui-installation","link":"#follow-the-sui-installation","children":[]},{"level":3,"title":"Clone DTP","slug":"clone-dtp","link":"#clone-dtp","children":[]},{"level":3,"title":"Initialize localnet","slug":"initialize-localnet","link":"#initialize-localnet","children":[]},{"level":3,"title":"Publish DTP Package (localnet)","slug":"publish-dtp-package-localnet","link":"#publish-dtp-package-localnet","children":[]},{"level":3,"title":"Run DTP Integration Test (localnet)","slug":"run-dtp-integration-test-localnet","link":"#run-dtp-integration-test-localnet","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.97,"words":291},"filePathRelative":"how-to/full_setup.md","localizedDate":"February 14, 2024","autoDesc":true}');export{w as comp,y as data}; diff --git a/assets/future_work.html-BqJ-TElc.js b/assets/future_work.html-BqJ-TElc.js new file mode 100644 index 0000000..ad59cf7 --- /dev/null +++ b/assets/future_work.html-BqJ-TElc.js @@ -0,0 +1 @@ +import{_ as n}from"./p2p_broadcast-DKREXEsi.js";import{_ as r}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as i,o as s,c,a as e,b as t,d as a,e as d}from"./app-DlOHg9Xr.js";const l={},p=d('

Future Work

Broadcasting Challenges

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

Data Deletion

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee --> Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

Data Consumption Confirmation

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

Encrypted Broadcasting

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services[^1]), but this is challenging and piracy can (at best) only be mitigated[^2].

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

',22),h={href:"https://en.wikipedia.org/wiki/Broadcast_encryption",target:"_blank",rel:"noopener noreferrer"},u={href:"https://en.wikipedia.org/wiki/Multicast_encryption",target:"_blank",rel:"noopener noreferrer"};function m(g,b){const o=i("ExternalLinkIcon");return s(),c("div",null,[p,e("p",null,[t("[^1]: Wikipedia "),e("a",h,[t("Broadcast Encryption"),a(o)])]),e("p",null,[t("[^2]: Wikipedia "),e("a",u,[t("Multicast Encryption"),a(o)])])])}const k=r(l,[["render",m],["__file","future_work.html.vue"]]),w=JSON.parse('{"path":"/docs/future_work.html","title":"Future Work","lang":"en-US","frontmatter":{"editLink":true,"description":"Future Work Broadcasting Challenges Data broadcasting will put pressure on fullnodes WebSocket event streaming services. Fullnodes may have low economic incentive to support suc...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/docs/future_work.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Future Work"}],["meta",{"property":"og:description","content":"Future Work Broadcasting Challenges Data broadcasting will put pressure on fullnodes WebSocket event streaming services. Fullnodes may have low economic incentive to support suc..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://dtp.dev/assets/images/p2p_broadcast.png?url"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Future Work"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Future Work\\",\\"image\\":[\\"https://dtp.dev/assets/images/p2p_broadcast.png?url\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Broadcasting Challenges","slug":"broadcasting-challenges","link":"#broadcasting-challenges","children":[]},{"level":2,"title":"Data Deletion","slug":"data-deletion","link":"#data-deletion","children":[]},{"level":2,"title":"Data Consumption Confirmation","slug":"data-consumption-confirmation","link":"#data-consumption-confirmation","children":[]},{"level":2,"title":"Encrypted Broadcasting","slug":"encrypted-broadcasting","link":"#encrypted-broadcasting","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.45,"words":436},"filePathRelative":"docs/future_work.md","localizedDate":"February 14, 2024","autoDesc":true}');export{k as comp,w as data}; diff --git a/assets/future_work.html-iK8jJpLI.js b/assets/future_work.html-iK8jJpLI.js new file mode 100644 index 0000000..eafb918 --- /dev/null +++ b/assets/future_work.html-iK8jJpLI.js @@ -0,0 +1 @@ +import{_ as n}from"./p2p_broadcast-DKREXEsi.js";import{_ as r}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as i,o as s,c,a as e,b as t,d as o,e as l}from"./app-DlOHg9Xr.js";const d={},p=l('

Future Work

Broadcasting Challenges

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

Data Deletion

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee --> Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

Data Consumption Confirmation

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

Encrypted Broadcasting

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services[^1]), but this is challenging and piracy can (at best) only be mitigated[^2].

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

',22),h={href:"https://en.wikipedia.org/wiki/Broadcast_encryption",target:"_blank",rel:"noopener noreferrer"},u={href:"https://en.wikipedia.org/wiki/Multicast_encryption",target:"_blank",rel:"noopener noreferrer"};function m(g,f){const a=i("ExternalLinkIcon");return s(),c("div",null,[p,e("p",null,[t("[^1]: Wikipedia "),e("a",h,[t("Broadcast Encryption"),o(a)])]),e("p",null,[t("[^2]: Wikipedia "),e("a",u,[t("Multicast Encryption"),o(a)])])])}const k=r(d,[["render",m],["__file","future_work.html.vue"]]),w=JSON.parse('{"path":"/ref/future_work.html","title":"Future Work","lang":"en-US","frontmatter":{"editLink":true,"description":"Future Work Broadcasting Challenges Data broadcasting will put pressure on fullnodes WebSocket event streaming services. Fullnodes may have low economic incentive to support suc...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/ref/future_work.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Future Work"}],["meta",{"property":"og:description","content":"Future Work Broadcasting Challenges Data broadcasting will put pressure on fullnodes WebSocket event streaming services. Fullnodes may have low economic incentive to support suc..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://dtp.dev/assets/images/p2p_broadcast.png?url"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:alt","content":"Future Work"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Future Work\\",\\"image\\":[\\"https://dtp.dev/assets/images/p2p_broadcast.png?url\\"],\\"dateModified\\":null,\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Broadcasting Challenges","slug":"broadcasting-challenges","link":"#broadcasting-challenges","children":[]},{"level":2,"title":"Data Deletion","slug":"data-deletion","link":"#data-deletion","children":[]},{"level":2,"title":"Data Consumption Confirmation","slug":"data-consumption-confirmation","link":"#data-consumption-confirmation","children":[]},{"level":2,"title":"Encrypted Broadcasting","slug":"encrypted-broadcasting","link":"#encrypted-broadcasting","children":[]}],"git":{"createdTime":null,"updatedTime":null,"contributors":[]},"readingTime":{"minutes":1.45,"words":436},"filePathRelative":"ref/future_work.md","autoDesc":true}');export{k as comp,w as data}; diff --git a/assets/icon/apple-icon-152.png b/assets/icon/apple-icon-152.png new file mode 100644 index 0000000000000000000000000000000000000000..434fcc3d5cdd2a03b4c4e41e915bf715f00127d7 GIT binary patch literal 3568 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 z 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 literal 0 HcmV?d00001 diff --git a/assets/icon/chrome-512.png b/assets/icon/chrome-512.png new file mode 100644 index 0000000000000000000000000000000000000000..a146f00036ded70bfe9491b0df7c9cfd816efce0 GIT binary patch literal 13251 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 literal 0 HcmV?d00001 diff --git a/assets/icon/guide-maskable.png b/assets/icon/guide-maskable.png new file mode 100644 index 0000000000000000000000000000000000000000..75449b6098bce400671eb4eac78c4ef687f431b2 GIT binary patch literal 2270 zcmai0X*?8q7yi%I48ml&c1A^ZV=OVq5Lt?vu@%Z-Y*}iItt4YfrY_Q^x1>yryva_; zFe)|58nTsKj4cY2n!4gnAKwq}@1EZ|=lMO)`8{9Gmvb0L+#JP46-5C6;?7R?Bq4Hs z7fRSb!V}|hA;3dzU2OrV&K27TKnOV|$cf|%z*$WI=otX~6iW1Y0OGI!ERq4h-vU7H zbU`!GN;rT99(1$^TNiV?+Jp=l>+I@)oDr2nNUQpK;LC){th2qXN8;G>`|-ol$K=7v z7s*@0XQoRGtycOneus(rix=qqn9M38&1ftc%Y>LdBu-~@ne(5Sve!Mm7&Y=T;>{<@ z?8($3=p_t^aI^_tB^OpivlvCXd~rW(VQnnk``xK@`TLz8cz(CVb4c+T5WW9zc|@N6 z#HT=KTb6WO$Ax@H_z?8v`E7u!;-O2f7w+o*dlre~*MrAI`IXSaKj1Opx1d^+NCc%3 z?9xH#E&CuT$?n?pwpUPq{b^c%g3)d23~paKvu;LYmz|^bC zV1j&}&#z;F$UEzb!)6H%8}yLxZdPWpOY0r8ktk!FQb@XnxqnA=B=Pw)vhJykiUd49 z)GtL_ECA^~q9SlVisxy!{Y^E8(h!C4lfNQ3?~Bv3cJgu&Ti0H|dR4g!xzA4#mUBQ(oyNwR*O&by(P}LEImf&exjTEHLi+}C&%Bz)+sTwT2hilKX@%|eoZ)M zRRKd4G14n^^!-&-GE*1niUr(~X|UV-|(;H!^9rpB}J`;_pS>{d_Z zu1tBmVV^3Cm8KFSGvdEokQvR1~fZj!j`%+;(4Ac5<5?ZC7wjIz!$d^@U zIM8e&088$9<{auD*q0D7Do0Mmjc_&3gb=x{yl74Y7Fm)Av6Mr>4!EyEO_DPpxe6_y zQ3H)A_ayhIx#TmTH{++aMgGdwBJ0WSCGZQi?)%1Iu74O1)D>Yy;EogP4J^{aj+Q<4 z5Xs`VPK~WvI|C{-F~nKH?p%95dv{sF1R4d+@F_ES-HlSuC_ifhp`B#=*Lpj%Yo9rz zC$Hm0s+TMDH{e|h+2?BwiHjz6c4)HA&OC>Pq*;z5r-1sgM(>wioOh5Ws%rTLcS^3e zx=El!N*@w~LvGqJL~)6y>eN@pwovL1?8SLq*WfadUbZN8N?8DmpI=@S zMT0}U7`u+}EcwBkcg4B>HJMqesl4Pn-d7Gz-fN?X^9-fn<~fZRv@Y6ap6K=$2uNpi#*Pf4g^m z{yUvHuZoYz4z`B~#4=iyXH(^wnImq@5A!e67i|B=%sGI&?T(nQAu#0=68(}T|H*Bge#ev+*1;K4iqEO6K%LH>w6Orsg;EJHxNMf@iV1JtnGTp zV?g^#XE^=!kYVw*h}R$V(SKH?S2i+Si6TU}8ubj<#_2k_0iRao@yL&z8oLca_Yy;6%S!sH68&tTKq2e| zY7M45wC0yq4e6Wf3gaLCyx#?wulGZH#$+Lc=L^JrL3{~q*ksmPQ#$UE9hi^ua8()5 z)In6ChptKcmR=!&jruS!=OqgxSQ7`){O#IEtdfK8-DnaTGeTZxeK+z#Kwe~WAwvae zpuM!f&e518MaE41tvH*_1VOE^p2%;lxHhfMb!&GGd0E7*ui+OPtZrA2{t7(v*`ctP zy>f*K+$ZQWIrj$~>{2paK^2@v2wAO2VI);M1+bQ#ST6#|18;m-rwtVuDfI`b zyoiK@?9KoB&wsk}F=u?Ga-U);507Zy$~lxZpeTrK_xQJKN>`Iyv7u}gN!4j?1PY%3 zjaY}Hv6O(=V0=(aun+(ai^J+0VfAsw9#~Vnkp&)Wri;bmvDo1VG3NgmqE1o5L(cqv U1Iw&dRcHXt4sP}pcI32w0BQ-(ivR!s literal 0 HcmV?d00001 diff --git a/assets/icon/ms-icon-144.png b/assets/icon/ms-icon-144.png new file mode 100644 index 0000000000000000000000000000000000000000..2464124422891d245517885bd71c2b49a7d29164 GIT binary patch literal 3657 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 Nz;ukXEAQGy{~Is6@Z10Z literal 0 HcmV?d00001 diff --git a/assets/image/advanced.svg b/assets/image/advanced.svg new file mode 100644 index 0000000..c27ede5 --- /dev/null +++ b/assets/image/advanced.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/blog.svg b/assets/image/blog.svg new file mode 100644 index 0000000..00fc40d --- /dev/null +++ b/assets/image/blog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/box.svg b/assets/image/box.svg new file mode 100644 index 0000000..9e6408e --- /dev/null +++ b/assets/image/box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/features.svg b/assets/image/features.svg new file mode 100644 index 0000000..6d62739 --- /dev/null +++ b/assets/image/features.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/github-dark.svg b/assets/image/github-dark.svg new file mode 100644 index 0000000..37fa923 --- /dev/null +++ b/assets/image/github-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/github-light.svg b/assets/image/github-light.svg new file mode 100644 index 0000000..d5e6491 --- /dev/null +++ b/assets/image/github-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/layout.svg b/assets/image/layout.svg new file mode 100644 index 0000000..da754b5 --- /dev/null +++ b/assets/image/layout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/image/markdown.svg b/assets/image/markdown.svg new file mode 100644 index 0000000..72056c9 --- /dev/null +++ b/assets/image/markdown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/HomeStackArrowCapy.png b/assets/images/HomeStackArrowCapy.png old mode 100644 new mode 100755 diff --git a/assets/images/design_terms.png b/assets/images/design_terms.png old mode 100644 new mode 100755 diff --git a/assets/images/example_rpc_firewall.png b/assets/images/example_rpc_firewall.png old mode 100644 new mode 100755 diff --git a/assets/images/example_web3.png b/assets/images/example_web3.png old mode 100644 new mode 100755 diff --git a/assets/images/free_icon.svg b/assets/images/free_icon.svg new file mode 100644 index 0000000..2dc2d6a --- /dev/null +++ b/assets/images/free_icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/home_high_level.png b/assets/images/home_high_level.png old mode 100644 new mode 100755 diff --git a/assets/images/home_top_capy.png b/assets/images/home_top_capy.png old mode 100644 new mode 100755 diff --git a/assets/images/multi_channels.png b/assets/images/multi_channels.png old mode 100644 new mode 100755 diff --git a/assets/images/p2p_broadcast.png b/assets/images/p2p_broadcast.png old mode 100644 new mode 100755 diff --git a/assets/images/propose-change.png b/assets/images/propose-change.png new file mode 100755 index 0000000000000000000000000000000000000000..6f2e44d5c84bb030b66d65a1dab9ec162cd09380 GIT binary patch literal 10764 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 S^^1d}4nQqK&GHA2!~Yjt+(LK& literal 0 HcmV?d00001 diff --git a/assets/images/ref_broadcast.png b/assets/images/ref_broadcast.png old mode 100644 new mode 100755 diff --git a/assets/images/ref_firewall.png b/assets/images/ref_firewall.png old mode 100644 new mode 100755 diff --git a/assets/images/ref_ha.png b/assets/images/ref_ha.png old mode 100644 new mode 100755 diff --git a/assets/images/ref_uni.png b/assets/images/ref_uni.png old mode 100644 new mode 100755 diff --git a/assets/images/setup_help_services.png b/assets/images/setup_help_services.png old mode 100644 new mode 100755 diff --git a/assets/images/total_vs_partial_order.PNG b/assets/images/total_vs_partial_order.PNG old mode 100644 new mode 100755 diff --git a/assets/images/total_vs_partial_order_small.PNG b/assets/images/total_vs_partial_order_small.PNG old mode 100644 new mode 100755 diff --git a/assets/index.html-2JbiJiHq.js b/assets/index.html-2JbiJiHq.js new file mode 100644 index 0000000..af1861c --- /dev/null +++ b/assets/index.html-2JbiJiHq.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as t,c as o,e as n}from"./app-DlOHg9Xr.js";const a={},r=n('

Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs.

Alternatively, the end-users may install the DTP services daemon to handle common cases (e.g making one side of the connection be a JSON-RPC server).

An end-user will first want to establish its own "unique contact point" on the network by creating a "Host Sui Object" using the DTP API.

Note: Most operation done through the DTP API can also be done on the command line with the "dtp" script.

An application can "ping" or "connect" to other Host object created by other apps. Each Host are uniquely identified by a <Host Object ID>.

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

On-Chain Firewall

For security reason, each Host Object are by default created "completely closed". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

Service Level Agreements (SLA)

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a "Service Level Agreement" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of "Typical" service level agreement to help minimize market confusion.

Service Level AgreementWho Pays
OpenDataStreamEveryone pay for their own transactions (txns).
AudioStream-FreeBroadcaster only.
JSON-RPC-BestEffortEveryone pay for their own txns. No response guaranteed.
JSON-RPC-RequesterPaidRPC Requester pays. Responder refunded through escrow.
Ping-RequesterPaidRPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

',18),i=[r];function s(c,l){return t(),o("div",null,i)}const p=e(a,[["render",s],["__file","index.html.vue"]]),u=JSON.parse('{"path":"/ref/","title":"Basic Concept","lang":"en-US","frontmatter":{"title":"Basic Concept","contributors":true,"editLink":true,"headerDepth":0,"description":"Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs. Alternatively, the end-users may install the DTP services d...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/ref/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Basic Concept"}],["meta",{"property":"og:description","content":"Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs. Alternatively, the end-users may install the DTP services d..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Basic Concept\\",\\"image\\":[\\"\\"],\\"dateModified\\":null,\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"On-Chain Firewall","slug":"on-chain-firewall","link":"#on-chain-firewall","children":[]},{"level":2,"title":"Service Level Agreements (SLA)","slug":"service-level-agreements-sla","link":"#service-level-agreements-sla","children":[]}],"git":{"createdTime":null,"updatedTime":null,"contributors":[]},"readingTime":{"minutes":1.47,"words":441},"filePathRelative":"ref/README.md","autoDesc":true}');export{p as comp,u as data}; diff --git a/assets/index.html-BSnE9a5s.js b/assets/index.html-BSnE9a5s.js new file mode 100644 index 0000000..5bf1a7d --- /dev/null +++ b/assets/index.html-BSnE9a5s.js @@ -0,0 +1 @@ +import{_ as n}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as l,o as a,c as r,a as e,b as t,d as o}from"./app-DlOHg9Xr.js";const s="/assets/images/total_vs_partial_order_small.PNG",c={},d=e("img",{src:s,style:{float:"left","padding-right":"20px"}},null,-1),p=e("p",null,[e("b",null," Why Sui and not blockchain 'x' ?"),e("br"),t(" SUI has good finality latency stability (low jitter) and network scalability (maintains per connection throughput regardless of total load)."),e("br")],-1),u=e("p",null,"Sui architecture provides two type of transactions:",-1),m=e("ul",null,[e("li",null,[e("p",null,"Simple Transaction with sub-second finality for data plane transfer (See 'partial ordering' illustration). This allows fast async/parallel transmission.")]),e("li",null,[e("p",null,"Narwhal/Bullshark consensus with 2-3 seconds finality used for slower control plane synchronization, like escrow services, reconfiguration, connection creation,etc...")])],-1),h={href:"https://www.cloudflare.com/learning/network-layer/what-is-the-control-plane/",target:"_blank",rel:"noopener noreferrer"},y={href:"https://docs.sui.io/learn/sui-compared",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"Why not simply use the good old, faster and free internet?",-1),b={href:"https://discord.gg/Erb6SwsVbH",target:"_blank",rel:"noopener noreferrer"};function g(_,k){const i=l("ExternalLinkIcon");return a(),r("div",null,[d,p,u,m,e("p",null,[t("With its flexible dual-type of transactions, Sui makes practical the implementation of common data + control plane design found in IP networks ( "),e("a",h,[t("Cloudflare explains it well"),o(i)]),t(" ).")]),e("p",null,[t("See "),e("a",y,[t("How Sui Differs from Other Blockchains?"),o(i)])]),f,e("p",null,[t("Join the "),e("a",b,[t("Discord community"),o(i)]),t(" and let's talk about it!")])])}const v=n(c,[["render",g],["__file","index.html.vue"]]),x=JSON.parse(`{"path":"/","title":"Home","lang":"en-US","frontmatter":{"home":true,"icon":"home","title":"Home","heroImage":"assets/images/home_top_capy.png","heroText":"","tagline":"","features":[{"title":"Create hybrid dApps","icon":"star-half-stroke","details":"Decentralized connection control, metering and crypto-economics
           +
Your existing off-chain services and data.","link":"/"},{"title":"Security and DDoS Protection","icon":"shield-halved","details":"
  • Scalable firewall built-in the Sui network!
  • Stop DDoS attacks even before it reaches your servers.
  • Keep IP addresses hidden (visible only to Sui node operators).
See firewall example...","link":"/examples/rpc_firewall.md"},{"title":"Privacy & Authenticity","icon":"user-lock","details":"
  • On-chain secret exchanges with end-to-end encryption.
  • Secured key/certificate installation from centralized servers.
  • Authenticity with signed data transfer.
","link":"/"},{"title":"Open-Source","icon":"/assets/images/free_icon.svg","details":"
  • Only code from developers for developers.
  • No Token, middlemen, commission or dev fee.
  • Only requires smart contracts execution costs (gas fee for Sui transactions).
Check the faq...","link":"/faq.md"},{"title":"High Availability","icon":"network-wired","details":"
  • Automatic failover and/or load balancing among your backend servers.
  • \\n
  • Maybe your service would benefit from censorship resistance of the Sui network?
  • \\n
  • Add serf-like coordination/governance among loosely coupled web2 servers.
","link":"/"},{"title":"Service Level Agreements","icon":"building-columns","details":"
  • Add fair Tokenomics to Web2: Pay per request, per byte, per RPC call etc...
  • \\n
  • Escrow for fair payments depending of success/failure of a query...
","link":"/"}],"description":" Why Sui and not blockchain 'x' ? SUI has good finality latency stability (low jitter) and network scalability (maintains per connection throughput regardless of total load). Su...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Home"}],["meta",{"property":"og:description","content":" Why Sui and not blockchain 'x' ? SUI has good finality latency stability (low jitter) and network scalability (maintains per connection throughput regardless of total load). Su..."}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"Home\\",\\"description\\":\\" Why Sui and not blockchain 'x' ? SUI has good finality latency stability (low jitter) and network scalability (maintains per connection throughput regardless of total load). Su...\\"}"]]},"headers":[],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.58,"words":473},"filePathRelative":"README.md","localizedDate":"February 14, 2024","autoDesc":true}`);export{v as comp,x as data}; diff --git a/assets/index.html-BbkzL85r.js b/assets/index.html-BbkzL85r.js new file mode 100644 index 0000000..e0bc8e7 --- /dev/null +++ b/assets/index.html-BbkzL85r.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as t,c as o,e as n}from"./app-DlOHg9Xr.js";const a={},r=n('

Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs.

Alternatively, the end-users may install the DTP services daemon to handle common cases (e.g making one side of the connection be a JSON-RPC server).

An end-user will first want to establish its own "unique contact point" on the network by creating a "Host Sui Object" using the DTP API.

Note: Most operation done through the DTP API can also be done on the command line with the "dtp" script.

An application can "ping" or "connect" to other Host object created by other apps. Each Host are uniquely identified by a <Host Object ID>.

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

On-Chain Firewall

For security reason, each Host Object are by default created "completely closed". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

Service Level Agreements (SLA)

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a "Service Level Agreement" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of "Typical" service level agreement to help minimize market confusion.

Service Level AgreementWho Pays
OpenDataStreamEveryone pay for their own transactions (txns).
AudioStream-FreeBroadcaster only.
JSON-RPC-BestEffortEveryone pay for their own txns. No response guaranteed.
JSON-RPC-RequesterPaidRPC Requester pays. Responder refunded through escrow.
Ping-RequesterPaidRPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

',18),i=[r];function s(c,l){return t(),o("div",null,i)}const h=e(a,[["render",s],["__file","index.html.vue"]]),u=JSON.parse('{"path":"/docs/","title":"Basic Concept","lang":"en-US","frontmatter":{"title":"Basic Concept","contributors":true,"editLink":true,"headerDepth":0,"description":"Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs. Alternatively, the end-users may install the DTP services d...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/docs/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Basic Concept"}],["meta",{"property":"og:description","content":"Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs. Alternatively, the end-users may install the DTP services d..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Basic Concept\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"On-Chain Firewall","slug":"on-chain-firewall","link":"#on-chain-firewall","children":[]},{"level":2,"title":"Service Level Agreements (SLA)","slug":"service-level-agreements-sla","link":"#service-level-agreements-sla","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.47,"words":441},"filePathRelative":"docs/README.md","localizedDate":"February 14, 2024","autoDesc":true}');export{h as comp,u as data}; diff --git a/assets/index.html-By-UCih8.js b/assets/index.html-By-UCih8.js new file mode 100644 index 0000000..f90bb29 --- /dev/null +++ b/assets/index.html-By-UCih8.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as o,o as a,c as n,d as r}from"./app-DlOHg9Xr.js";const c={};function p(s,l){const t=o("Catalog");return a(),n("div",null,[r(t)])}const d=e(c,[["render",p],["__file","index.html.vue"]]),_=JSON.parse('{"path":"/how-to/","title":"How to","lang":"en-US","frontmatter":{"title":"How to","article":false,"feed":false,"sitemap":false,"description":"","head":[["meta",{"property":"og:url","content":"https://dtp.dev/how-to/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"How to"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"article:author","content":"dtp.dev"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"How to\\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0,"words":1},"filePathRelative":null,"autoDesc":true}');export{d as comp,_ as data}; diff --git a/assets/index.html-K9gGP3vT.js b/assets/index.html-K9gGP3vT.js new file mode 100644 index 0000000..fbd09cb --- /dev/null +++ b/assets/index.html-K9gGP3vT.js @@ -0,0 +1 @@ +import{_ as i}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as n,o as a,c as s,a as e,b as t,d as r}from"./app-DlOHg9Xr.js";const l={},c=e("p",null,"For DTP and any SDK/tool projects welcome to join:",-1),d={href:"https://discord.gg/Erb6SwsVbH",target:"_blank",rel:"noopener noreferrer"},u=e("p",null,"For Sui specific discussions:",-1),p={href:"https://discord.gg/sui",target:"_blank",rel:"noopener noreferrer"},m={href:"https://forums.sui.io/",target:"_blank",rel:"noopener noreferrer"},h=e("h2",{id:"contributors",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contributors"},[e("span",null,"Contributors")])],-1),_=e("p",null,[e("strong",null,"Mario Fortier"),t(" - Lead Developer"),e("br")],-1),f={href:"https://www.linkedin.com/in/mfortier/",target:"_blank",rel:"noopener noreferrer"},b=e("br",null,null,-1),g=e("li",null,[t("Discord username : Mhax#6164"),e("br")],-1),y={href:"https://github.com/mario4tier",target:"_blank",rel:"noopener noreferrer"},D=e("p",null,"(Join, contribute and have your name added here...)",-1);function S(k,v){const o=n("ExternalLinkIcon");return a(),s("div",null,[c,e("ul",null,[e("li",null,[e("a",d,[t("ChainMovers Discord"),r(o)])])]),u,e("ul",null,[e("li",null,[e("p",null,[e("a",p,[t("Sui Official Discord"),r(o)])])]),e("li",null,[e("p",null,[e("a",m,[t("Sui Official Forum"),r(o)])])])]),h,_,e("ul",null,[e("li",null,[t("LinkedIn: "),e("a",f,[t("https://www.linkedin.com/in/mfortier/"),r(o)]),b]),g,e("li",null,[t("Github username : "),e("a",y,[t("https://github.com/mario4tier"),r(o)])])]),D])}const w=i(l,[["render",S],["__file","index.html.vue"]]),x=JSON.parse('{"path":"/community/","title":"Community","lang":"en-US","frontmatter":{"title":"Community","headerDepth":0,"editLink":true,"description":"For DTP and any SDK/tool projects welcome to join: ChainMovers Discord For Sui specific discussions: Sui Official Discord Sui Official Forum Contributors Mario Fortier - Lead De...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/community/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Community"}],["meta",{"property":"og:description","content":"For DTP and any SDK/tool projects welcome to join: ChainMovers Discord For Sui specific discussions: Sui Official Discord Sui Official Forum Contributors Mario Fortier - Lead De..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Community\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Contributors","slug":"contributors","link":"#contributors","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.2,"words":60},"filePathRelative":"community/README.md","localizedDate":"February 14, 2024","autoDesc":true}');export{w as comp,x as data}; diff --git a/assets/index.html-xbvo-U6r.js b/assets/index.html-xbvo-U6r.js new file mode 100644 index 0000000..38fd569 --- /dev/null +++ b/assets/index.html-xbvo-U6r.js @@ -0,0 +1 @@ +import{_ as r}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as l,o as c,c as d,a as e,b as t,d as o,w as i,e as p}from"./app-DlOHg9Xr.js";const u={},h=e("p",null,"DTP provides networking building blocks that can be applied in many ways.",-1),m=e("p",null,"You will find on this page a few inspiring ideas.",-1),g={href:"../how-to/install.md?url"},w=e("h2",{id:"which-layer-do-you-need-to-work-with",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#which-layer-do-you-need-to-work-with"},[e("span",null,"Which layer do you need to work with?")])],-1),y=e("p",null,"DTP features are available in roughly 3 layers (by increasing level of difficulty):",-1),f=e("li",null,[e("p",null,[e("b",null,"DTP Services Daemon"),t(" Similar to NGINX, Cloudflare, HAProxy... These are for proxy/forward/firewall services. You will simply be "),e("em",null,"configuring"),t(' how your data flows between your apps and servers. Your existing apps just use standard TCP/IP sockets (e.g. "localhost:port" URL) to interface with the DTP services daemon.')])],-1),_=e("li",null,[e("p",null,[e("b",null,"DTP Protocols"),t(` Think "TCP". The DTP/Sui SDKs allows developers to have more control for connecting any mix of web2 apps (webapp, client/servers...). You will need to write Rust and/or Typescript apps. This is also the solution to eliminate having to install the DTP Services Daemon on your end-users' devices.`)])],-1),v=e("b",null,"DTP Sui Move Packages",-1),b=e("p",null,'For most users, you will deal only with the "easiest" layer, the "DTP Services Daemon".',-1),T={href:"https://discord.gg/Erb6SwsVbH",target:"_blank",rel:"noopener noreferrer"},k=e("h2",{id:"examples-ideas",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#examples-ideas"},[e("span",null,"Examples/Ideas")])],-1),P=e("p",null,[e("strong",null,"Client/Server")],-1),D=e("p",null,[e("strong",null,"Encrypted Messaging")],-1),x=e("ul",null,[e("li",null,'Add traditional user/password login to a dApp. The goal is to allow access to the same "user account" even if done from a different wallet (client address). Implementation often requires "secret messaging" between a centralized server and the Web3 apps.'),e("li",null,"Any user-to-user data transfer "),e("li",null,"Anonymous Tips Line (with potential reward in return).")],-1),S=e("p",null,[e("strong",null,"Networking / Infrastructure")],-1),C=e("li",null,"Zookeeper, Consul, Serf-like services for discovery and consensus among off-chain servers.",-1),I=p("

Firewall

  • Rate limit access to a back-end server (either bandwidth or request)
  • Allow/block origin (using authentication)

Crypto-Economics

  • Any service charging for content access (in addition to gas cost). DTP provides generic per byte and/or per request escrow service (to meter pre-agreed cost, limit and quantity... not quality).
  • Pre-paid subscription per day/month (epoch driven?).
  • Various escrow service that allows to shift the transport cost completely at the origin or destination (gas always paid by sender, but escrow service handles fair refund).

Public Broadcasting

  • Allow live broadcasting to automatically turn on/off upon enough fund contributed (thus saving the producer from any expense when no-one is listening).
  • Public broadcast performed upon enough ticket sold.
  • Tip/Request/Message/Audience participation line attach to a public event channel.
",6);function A(R,E){const s=l("HopeIcon"),n=l("RouteLink"),a=l("ExternalLinkIcon");return c(),d("div",null,[h,m,e("p",null,[t("When ready "),e("a",g,[o(s,{icon:"arrow-right"}),t(" Go to choose your installation setup ...")]),t(".")]),w,y,e("ul",null,[f,_,e("li",null,[e("p",null,[v,t(" Innovations particular to Sui, such as RPC escrows, "),o(n,{to:"/docs/design.html#multi-channel-connection"},{default:i(()=>[t("data streaming")]),_:1}),t(", coins&call equivocation mitigation, metering etc... you will likely be deeply involve into web3 development at this point.")])])]),b,e("p",null,[t("If not sure how to proceed for your specific need, then please open a discussion on "),e("a",T,[t("Discord"),o(a)]),t(".")]),k,P,e("ul",null,[e("li",null,[t("Web3 frontends connecting to a centralized JSON-RPC backend ("),o(n,{to:"/examples/rpc_firewall.html"},{default:i(()=>[t("More info")]),_:1}),t(")")]),e("li",null,[t("Rust/Typescript Web3 Client to centralized TCP Server ("),o(n,{to:"/examples/web3_rust.html"},{default:i(()=>[t("More info")]),_:1}),t(")")])]),D,x,S,e("ul",null,[C,e("li",null,[t("UDP, TCP, QUIC/UDP Tunneling: Transport IP protocols packets within a DTP connection for point-to-point applications (See "),o(n,{to:"/how-to/install.html#choice-1-of-3-simplified-dtp-services-deployment"},{default:i(()=>[t("DTP Services Daemon")]),_:1}),t(" for an alternative)")])]),I])}const N=r(u,[["render",A],["__file","index.html.vue"]]),q=JSON.parse('{"path":"/examples/","title":"Use Cases","lang":"en-US","frontmatter":{"title":"Use Cases","contributors":true,"editLink":true,"headerDepth":0,"description":"DTP provides networking building blocks that can be applied in many ways. You will find on this page a few inspiring ideas. When ready . Which layer do you need to work with? DT...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/examples/"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:title","content":"Use Cases"}],["meta",{"property":"og:description","content":"DTP provides networking building blocks that can be applied in many ways. You will find on this page a few inspiring ideas. When ready . Which layer do you need to work with? DT..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Use Cases\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Which layer do you need to work with?","slug":"which-layer-do-you-need-to-work-with","link":"#which-layer-do-you-need-to-work-with","children":[]},{"level":2,"title":"Examples/Ideas","slug":"examples-ideas","link":"#examples-ideas","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.71,"words":512},"filePathRelative":"examples/README.md","localizedDate":"February 14, 2024","autoDesc":true}');export{N as comp,q as data}; diff --git a/assets/install.html-BizGowkj.js b/assets/install.html-BizGowkj.js new file mode 100644 index 0000000..d1890b0 --- /dev/null +++ b/assets/install.html-BizGowkj.js @@ -0,0 +1 @@ +import{_ as e}from"./plugin-vue_export-helper-DlAUqK2U.js";import{o as t,c as o,e as i}from"./app-DlOHg9Xr.js";const n="/assets/images/setup_help_services.png",s={},a=i('

There are 3 ways to install DTP.

Choose the one that best fits your needs and you can always later switch from one to the other.

Choice 1 of 3: Full Development Setup

This is the only setup available for now.

Recommended if you need any of these:

  • Develop Sui Move package (with or without DTP)

  • Create your own Rust application using DTP and/or Sui Rust SDK.

  • Development of a new DTP service (e.g. you are writing your own backend Rust servers and do not want to use the DTP Services daemon as an intermediate).

The setup includes a Sui development framework (Suibase), the DTP Service Daemon runtime, all the DTP SDKs and some utility scripts for quicker edit/publish/debug development cycles.

DTP dev framework is not conflicting with other Sui installations (e.g. official Mysten Labs cargo install) and can be uninstalled easily.

Go to Full Setup ...

Choice 2 of 3: DTP Services Runtime (No Coding)

Not yet implemented

For now, use the Full Development setup, which includes the DTP Services runtime.

Choose this setup if you only need one or more of the following feature:

  • Make your existing server API accessible on the Sui network (e.g. REST, JSON-RPC etc...)

  • Make a local directory content accessible on the Sui network (be a "file server")

  • Allow other user on the network to discover and ping your server.

  • Have end-users (e.g. frontend app) install their own DTP runtime as a local proxy to your backend services.

This setup does not require any coding skills, just configuration in a text file and using the dtp command line tool.

Choice 3 of 3: DTP Typescript SDK (NPM Packages Only)

Not yet implemented

The DTP Typescript SDK is not yet written. Priority is to develop the Rust SDK first.

Choose this setup if you only need to develop front-end apps doing DTP connections to existing services and not require the DTP service daemon installation.

',18),r=[a];function l(p,c){return t(),o("div",null,r)}const u=e(s,[["render",l],["__file","install.html.vue"]]),m=JSON.parse('{"path":"/how-to/install.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":"There are 3 ways to install DTP. Choose the one that best fits your needs and you can always later switch from one to the other. Choice 1 of 3: Full Development Setup This is th...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/how-to/install.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":"There are 3 ways to install DTP. Choose the one that best fits your needs and you can always later switch from one to the other. Choice 1 of 3: Full Development Setup This is th..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://dtp.dev/assets/images/setup_help_services.png?url"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"https://dtp.dev/assets/images/setup_help_services.png?url\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[{"level":2,"title":"Choice 1 of 3: Full Development Setup","slug":"choice-1-of-3-full-development-setup","link":"#choice-1-of-3-full-development-setup","children":[]},{"level":2,"title":"Choice 2 of 3: DTP Services Runtime (No Coding)","slug":"choice-2-of-3-dtp-services-runtime-no-coding","link":"#choice-2-of-3-dtp-services-runtime-no-coding","children":[]},{"level":2,"title":"Choice 3 of 3: DTP Typescript SDK (NPM Packages Only)","slug":"choice-3-of-3-dtp-typescript-sdk-npm-packages-only","link":"#choice-3-of-3-dtp-typescript-sdk-npm-packages-only","children":[]}],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":1.14,"words":341},"filePathRelative":"how-to/install.md","localizedDate":"February 14, 2024","autoDesc":true}');export{u as comp,m as data}; diff --git a/assets/intro.html-DJw2Nump.js b/assets/intro.html-DJw2Nump.js new file mode 100644 index 0000000..17bc3da --- /dev/null +++ b/assets/intro.html-DJw2Nump.js @@ -0,0 +1 @@ +import{_ as i}from"./plugin-vue_export-helper-DlAUqK2U.js";import{r as n,o as r,c as s,a as t,b as e,d as a}from"./app-DlOHg9Xr.js";const c="/assets/images/home_high_level.png",l={},d=t("p",null,[t("strong",null,"What is DTP?")],-1),p=t("p",null,"It is a TCP-Like protocol facilitating data transfer between any web2 applications, with additional Web3 features such as services monetization, anonymity and security.",-1),m=t("img",{src:c,style:{display:"block","margin-left":"auto","margin-right":"auto"}},null,-1),u=t("p",null,"DTP facilitate high-level data transfer, such as audio, video, RPC calls etc...",-1),h=t("p",null,"DTP can be integrated into your own Rust/Typescript apps (frontend and/or backend).",-1),_=t("p",null,'Alternatively, you can direct your TCP/IP socket (or websocket) traffic toward a local DTP Services daemon. This daemon takes care of adding Web3 capabilities to your existing Web2 traffic (e.g. handles "per request" micro-payments).',-1),y={href:"../examples/?url"},f={href:"../how-to/install.md?url"};function g(b,T){const o=n("HopeIcon");return r(),s("div",null,[d,p,m,u,h,_,t("p",null,[e("Not sure if a good fit? "),t("a",y,[a(o,{icon:"arrow-right"}),e(" Check a few use cases")]),e(".")]),t("p",null,[e("Ready to try it ? "),t("a",f,[a(o,{icon:"arrow-right"}),e(" Go to Installation")]),e(".")])])}const P=i(l,[["render",g],["__file","intro.html.vue"]]),k=JSON.parse('{"path":"/intro.html","title":"","lang":"en-US","frontmatter":{"editLink":true,"description":"What is DTP? It is a TCP-Like protocol facilitating data transfer between any web2 applications, with additional Web3 features such as services monetization, anonymity and secur...","head":[["meta",{"property":"og:url","content":"https://dtp.dev/intro.html"}],["meta",{"property":"og:site_name","content":"Decentralized Transport Protocol"}],["meta",{"property":"og:description","content":"What is DTP? It is a TCP-Like protocol facilitating data transfer between any web2 applications, with additional Web3 features such as services monetization, anonymity and secur..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-14T03:11:10.000Z"}],["meta",{"property":"article:author","content":"dtp.dev"}],["meta",{"property":"article:modified_time","content":"2024-02-14T03:11:10.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-14T03:11:10.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"dtp.dev\\",\\"url\\":\\"https://dtp.dev\\"}]}"]]},"headers":[],"git":{"createdTime":1707880270000,"updatedTime":1707880270000,"contributors":[{"name":"mario4tier","email":"mario4tier@users.noreply.github.com","commits":1}]},"readingTime":{"minutes":0.49,"words":146},"filePathRelative":"intro.md","localizedDate":"February 14, 2024","autoDesc":true}');export{P as comp,k as data}; diff --git a/assets/javascripts/bundle.b7178837.min.js b/assets/javascripts/bundle.b7178837.min.js deleted file mode 100644 index f704abc..0000000 --- a/assets/javascripts/bundle.b7178837.min.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict";(()=>{var Ni=Object.create;var kr=Object.defineProperty;var Vi=Object.getOwnPropertyDescriptor;var zi=Object.getOwnPropertyNames,qt=Object.getOwnPropertySymbols,qi=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty,dn=Object.prototype.propertyIsEnumerable;var mn=(e,t,r)=>t in e?kr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,j=(e,t)=>{for(var r in t||(t={}))Hr.call(t,r)&&mn(e,r,t[r]);if(qt)for(var r of qt(t))dn.call(t,r)&&mn(e,r,t[r]);return e};var hn=(e,t)=>{var r={};for(var n in e)Hr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&qt)for(var n of qt(e))t.indexOf(n)<0&&dn.call(e,n)&&(r[n]=e[n]);return r};var Kt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Ki=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of zi(t))!Hr.call(e,o)&&o!==r&&kr(e,o,{get:()=>t[o],enumerable:!(n=Vi(t,o))||n.enumerable});return e};var Lt=(e,t,r)=>(r=e!=null?Ni(qi(e)):{},Ki(t||!e||!e.__esModule?kr(r,"default",{value:e,enumerable:!0}):r,e));var vn=Kt((Rr,bn)=>{(function(e,t){typeof Rr=="object"&&typeof bn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Rr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(_){return!!(_&&_!==document&&_.nodeName!=="HTML"&&_.nodeName!=="BODY"&&"classList"in _&&"contains"in _.classList)}function p(_){var Ve=_.type,H=_.tagName;return!!(H==="INPUT"&&a[Ve]&&!_.readOnly||H==="TEXTAREA"&&!_.readOnly||_.isContentEditable)}function c(_){_.classList.contains("focus-visible")||(_.classList.add("focus-visible"),_.setAttribute("data-focus-visible-added",""))}function l(_){_.hasAttribute("data-focus-visible-added")&&(_.classList.remove("focus-visible"),_.removeAttribute("data-focus-visible-added"))}function f(_){_.metaKey||_.altKey||_.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(_){n=!1}function d(_){s(_.target)&&(n||p(_.target))&&c(_.target)}function h(_){s(_.target)&&(_.target.classList.contains("focus-visible")||_.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),l(_.target))}function v(_){document.visibilityState==="hidden"&&(o&&(n=!0),Q())}function Q(){document.addEventListener("mousemove",K),document.addEventListener("mousedown",K),document.addEventListener("mouseup",K),document.addEventListener("pointermove",K),document.addEventListener("pointerdown",K),document.addEventListener("pointerup",K),document.addEventListener("touchmove",K),document.addEventListener("touchstart",K),document.addEventListener("touchend",K)}function oe(){document.removeEventListener("mousemove",K),document.removeEventListener("mousedown",K),document.removeEventListener("mouseup",K),document.removeEventListener("pointermove",K),document.removeEventListener("pointerdown",K),document.removeEventListener("pointerup",K),document.removeEventListener("touchmove",K),document.removeEventListener("touchstart",K),document.removeEventListener("touchend",K)}function K(_){_.target.nodeName&&_.target.nodeName.toLowerCase()==="html"||(n=!1,oe())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Q(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var gn=Kt(Pr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var l={next:function(){var f=c.shift();return{done:f===void 0,value:f}}};return r&&(l[Symbol.iterator]=function(){return l}),l},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(f){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof f;if(m!=="undefined")if(m==="string")f!==""&&this._fromString(f);else if(f instanceof c){var d=this;f.forEach(function(oe,K){d.append(K,oe)})}else if(f!==null&&m==="object")if(Object.prototype.toString.call(f)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var f=0;f1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Pr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(p,c){typeof p!="string"&&(p=String(p)),c&&typeof c!="string"&&(c=String(c));var l=document,f;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),l=document.implementation.createHTMLDocument(""),f=l.createElement("base"),f.href=c,l.head.appendChild(f);try{if(f.href.indexOf(c)!==0)throw new Error(f.href)}catch(_){throw new Error("URL unable to set base "+c+" due to "+_)}}var m=l.createElement("a");m.href=p,f&&(l.body.appendChild(m),m.href=m.href);var d=l.createElement("input");if(d.type="url",d.value=p,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Q=!0,oe=this;["append","delete","set"].forEach(function(_){var Ve=h[_];h[_]=function(){Ve.apply(h,arguments),v&&(Q=!1,oe.search=h.toString(),Q=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var K=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==K&&(K=this.search,Q&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(p){Object.defineProperty(a,p,{get:function(){return this._anchorElement[p]},set:function(c){this._anchorElement[p]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(p){s(p)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(p){this._anchorElement.search=p,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var p=this;return function(){return p.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(p){this._anchorElement.href=p,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(p){this._anchorElement.pathname=p},enumerable:!0},origin:{get:function(){var p={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=p&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(p){},enumerable:!0},username:{get:function(){return""},set:function(p){},enumerable:!0}}),i.createObjectURL=function(p){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(p){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Pr)});var an=Kt((Wt,on)=>{(function(t,r){typeof Wt=="object"&&typeof on=="object"?on.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Wt=="object"?Wt.ClipboardJS=r():t.ClipboardJS=r()})(Wt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Di}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function m(N){try{return document.execCommand(N)}catch(L){return!1}}var d=function(L){var M=f()(L);return m("cut"),M},h=d;function v(N){var L=document.documentElement.getAttribute("dir")==="rtl",M=document.createElement("textarea");M.style.fontSize="12pt",M.style.border="0",M.style.padding="0",M.style.margin="0",M.style.position="absolute",M.style[L?"right":"left"]="-9999px";var I=window.pageYOffset||document.documentElement.scrollTop;return M.style.top="".concat(I,"px"),M.setAttribute("readonly",""),M.value=N,M}var Q=function(L,M){var I=v(L);M.container.appendChild(I);var W=f()(I);return m("copy"),I.remove(),W},oe=function(L){var M=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},I="";return typeof L=="string"?I=Q(L,M):L instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(L==null?void 0:L.type)?I=Q(L.value,M):(I=f()(L),m("copy")),I},K=oe;function _(N){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?_=function(M){return typeof M}:_=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},_(N)}var Ve=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},M=L.action,I=M===void 0?"copy":M,W=L.container,G=L.target,Ie=L.text;if(I!=="copy"&&I!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(G!==void 0)if(G&&_(G)==="object"&&G.nodeType===1){if(I==="copy"&&G.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(I==="cut"&&(G.hasAttribute("readonly")||G.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Ie)return K(Ie,{container:W});if(G)return I==="cut"?h(G):K(G,{container:W})},H=Ve;function B(N){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?B=function(M){return typeof M}:B=function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M},B(N)}function ie(N,L){if(!(N instanceof L))throw new TypeError("Cannot call a class as a function")}function me(N,L){for(var M=0;M0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof W.action=="function"?W.action:this.defaultAction,this.target=typeof W.target=="function"?W.target:this.defaultTarget,this.text=typeof W.text=="function"?W.text:this.defaultText,this.container=B(W.container)==="object"?W.container:document.body}},{key:"listenClick",value:function(W){var G=this;this.listener=c()(W,"click",function(Ie){return G.onClick(Ie)})}},{key:"onClick",value:function(W){var G=W.delegateTarget||W.currentTarget,Ie=this.action(G)||"copy",zt=H({action:Ie,container:this.container,target:this.target(G),text:this.text(G)});this.emit(zt?"success":"error",{action:Ie,text:zt,trigger:G,clearSelection:function(){G&&G.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(W){return Cr("action",W)}},{key:"defaultTarget",value:function(W){var G=Cr("target",W);if(G)return document.querySelector(G)}},{key:"defaultText",value:function(W){return Cr("text",W)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(W){var G=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return K(W,G)}},{key:"cut",value:function(W){return h(W)}},{key:"isSupported",value:function(){var W=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],G=typeof W=="string"?[W]:W,Ie=!!document.queryCommandSupported;return G.forEach(function(zt){Ie=Ie&&!!document.queryCommandSupported(zt)}),Ie}}]),M}(s()),Di=Wi},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(l,f,m,d,h){var v=c.apply(this,arguments);return l.addEventListener(m,v,h),{destroy:function(){l.removeEventListener(m,v,h)}}}function p(l,f,m,d,h){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(v){return s(v,f,m,d,h)}))}function c(l,f,m,d){return function(h){h.delegateTarget=a(h.target,f),h.delegateTarget&&d.call(l,h)}}n.exports=p},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function p(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return l(m,d,h);if(a.string(m))return f(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function l(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function f(m,d,h){return s(document.body,m,d,h)}n.exports=p},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p{"use strict";var gs=/["'&<>]/;ci.exports=ys;function ys(e){var t=""+e,r=gs.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,p,c,l)=>{if(s===this.url.toString()){let f=new ErrorEvent("error",{message:a,filename:s,lineno:p,colno:c,error:l});this.dispatchEvent(f),this.onerror&&this.onerror(f)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + How to propose fix/change to the website? | Decentralized Transport Protocol + + + + + +
Skip to main content

How to propose fix/change to the website?


Anyone with a Github account can participate.

The website is built from markdown files (.md) and served directly from githubopen in new window.

Open the editor with the "Edit this pages on Github" link at the bottom.

When ready to propose your changes just select "Create a new branch" and give it a name:
Propose Changes

Your proposed changes will be merged after review.

Editing the website on your machine (advanced contributors)

If you prefer to preview exactly your change, then you need to run vuepress on your machine and modify the markdown files with an editor (e.g. VSCode).

Prerequisites:

For the one-time vuepress installation do:

$ cd ~/suibase/workdirs/common/extensions/dtp/docs
+$ pnpm install
+

To start vuepress (the server) do:

$ cd ~/suibase/workdirs/common/extensions/dtp/docs
+$ pnpm start
+...
+Open your browser at http://localhost:8080
+

The browser updates as you change files under docs/src

See https://theme-hope.vuejs.press/guide/open in new window for advanced markdown features.

Submit your changes as a pull request, just ask as needed (not as hard as it seems once you do it once).

+ + + diff --git a/community/index.html b/community/index.html index 6d0644a..53f84c7 100644 --- a/community/index.html +++ b/community/index.html @@ -1 +1,40 @@ - Community - DTP - Decentralized Transport Protocol
\ No newline at end of file + + + + + + + + + + Community | Decentralized Transport Protocol + + + + + + + + + diff --git a/docs/api_rust.html b/docs/api_rust.html new file mode 100644 index 0000000..ead7adc --- /dev/null +++ b/docs/api_rust.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/docs/api_typescript.html b/docs/api_typescript.html new file mode 100644 index 0000000..9864cf4 --- /dev/null +++ b/docs/api_typescript.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/docs/design.html b/docs/design.html new file mode 100644 index 0000000..93dee23 --- /dev/null +++ b/docs/design.html @@ -0,0 +1,40 @@ + + + + + + + + + + Design | Decentralized Transport Protocol + + + + + +
Skip to main content

Design


Target Audience

Developers should first read the API they intend to use.

This document is for developers curious about DTP inner works.

At high level, how is the Sui Network used?

Sui owned objects are used for unidirectional data transfer with sub-second latency (See Simple Transactionopen in new window in Sui docs).

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data "exit" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be "observed" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most "control plane" synchronizations.

DTP Glossary

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

Objects: Usually refer to Sui objects (See Sui Docsopen in new window)

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be "sent data can be deleted from network storage after 48 hours (2 epochs)". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

Firewall

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

Multi-Channel Connection

Media byte streams are ineviteably divided into transaction "block" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

Some estimations (See on Google Sheetopen in new window):

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

High-Availability and Load Balancing

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should "pull it".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

Uni-directional Transfer

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

Public Broadcasting

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic "on air" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).

There are also some technical challenges particular to broadcasting (See Future Work).

+ + + diff --git a/docs/future_work.html b/docs/future_work.html new file mode 100644 index 0000000..1f2ce0f --- /dev/null +++ b/docs/future_work.html @@ -0,0 +1,40 @@ + + + + + + + + + + Future Work | Decentralized Transport Protocol + + + + + +
Skip to main content

Future Work


Future Work

Broadcasting Challenges

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

Data Deletion

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee --> Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

Data Consumption Confirmation

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

Encrypted Broadcasting

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services[^1]), but this is challenging and piracy can (at best) only be mitigated[^2].

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

[^1]: Wikipedia Broadcast Encryptionopen in new window

[^2]: Wikipedia Multicast Encryptionopen in new window

+ + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..9fac18d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + Basic Concept | Decentralized Transport Protocol + + + + + +
Skip to main content

Basic Concept


Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs.

Alternatively, the end-users may install the DTP services daemon to handle common cases (e.g making one side of the connection be a JSON-RPC server).

An end-user will first want to establish its own "unique contact point" on the network by creating a "Host Sui Object" using the DTP API.

Note: Most operation done through the DTP API can also be done on the command line with the "dtp" script.

An application can "ping" or "connect" to other Host object created by other apps. Each Host are uniquely identified by a <Host Object ID>.

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

On-Chain Firewall

For security reason, each Host Object are by default created "completely closed". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

Service Level Agreements (SLA)

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a "Service Level Agreement" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of "Typical" service level agreement to help minimize market confusion.

Service Level AgreementWho Pays
OpenDataStreamEveryone pay for their own transactions (txns).
AudioStream-FreeBroadcaster only.
JSON-RPC-BestEffortEveryone pay for their own txns. No response guaranteed.
JSON-RPC-RequesterPaidRPC Requester pays. Responder refunded through escrow.
Ping-RequesterPaidRPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

+ + + diff --git a/docs/scripts.html b/docs/scripts.html new file mode 100644 index 0000000..1b8d3ca --- /dev/null +++ b/docs/scripts.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/example/rpc_firewall/index.html b/example/rpc_firewall/index.html deleted file mode 100644 index 9ede53f..0000000 --- a/example/rpc_firewall/index.html +++ /dev/null @@ -1 +0,0 @@ - JSON-RPC Firewall - DTP - Decentralized Transport Protocol

JSON-RPC Firewall

In this example, a Web3 application access a Web2 server providing a JSON-RPC API to its customer.

One of the goal is to protect the Web2 server from DDoS attack, in particular, hide its IP address.

A DTP "Services Daemon" runs as a TCP/IP proxy on the same machine as the web2 server.

Since the sender has to pay for all the data byte transmission costs through the Sui network, an attack is costly and mostly futile.

The server IP address is visible only to the Sui nodes (not to the Web3 users on the other side of the Sui network). This mitigates direct traditional IP attacks. The server is not completely hidden, but the owner can control its Sui node partners (in similar way that one choose to, say, trust a reputable company such as Cloudflare).

On the drawing, everything in green and blue is provided by DTP and the Sui infrastructure respectively. The application developer provides only what is shown in yellow.

In this example the Web3 app contact the hidden web2 IP server using the <Host Object ID>:8923 address and DTP takes care of the safe data transfer.

Work-In-Progress... there is more to it... such as mitigation with dynamic <Host ObjectID> to more than one origin IP mapping

\ No newline at end of file diff --git a/example/web3_rust/index.html b/example/web3_rust/index.html deleted file mode 100644 index e6f14ae..0000000 --- a/example/web3_rust/index.html +++ /dev/null @@ -1 +0,0 @@ - Web3 Rust Server - DTP - Decentralized Transport Protocol

Web3 Client / Rust Server

Connect any frontend to both a centralized and decentralized backend.

Incomplete Documentation - Work-In-Progress

\ No newline at end of file diff --git a/examples/index.html b/examples/index.html index af9aec4..5bcbb1c 100644 --- a/examples/index.html +++ b/examples/index.html @@ -1 +1,40 @@ - Application Examples - DTP - Decentralized Transport Protocol

Applications Example

DTP provides networking building blocks that can be applied in many ways.

You will find on this page a few inspiring ideas.

DTP features are made available in roughly 3 layers (in increasing level of difficulty):

  • DTP Services Daemon Similar to NGINX/Cloudflare/HAProxy. These are for proxy/forward/firewall services. You will simply be configuring how your data flows between your apps and hosts.

  • DTP Protocols Think "TCP". The DTP/Sui SDKs allows developers to create connections between web2 and web3 apps. You will need to write Rust and/or Typescript apps.

  • DTP Sui Move Packages Innovations particular to Sui, such as RPC escrows, data streaming, coins&call equivocation mitigation, metering etc... you will likely be deeply involve into web3 development at this point.

For most users, you will deal only with the "easiest" layer, the "DTP Services Daemon".

If not sure how to proceed for your specific need, then please open a discussion on Discord.

When ready Go to choose your installation setup ....

Client/Server

  • Web3 frontends connecting to a centralized JSON-RPC backend (More info)
  • Rust/Typescript Web3 Client to centralized TCP Server (More info)

Encrypted Messaging

  • Add traditional user/password login to a dApp. The goal is to allow access to the same "user account" even if done from a different wallet (client address). Implementation often requires "secret messaging" between a centralized server and the Web3 apps.
  • Any user-to-user data transfer
  • Anonymous Tips Line (with potential reward in return).

Networking / Infrastructure

  • Zookeeper, Consul, Serf-like services for discovery and consensus among off-chain servers.
  • UDP, TCP, QUIC/UDP Tunneling: Transport IP protocols packets within a DTP connection for point-to-point applications (See DTP Services Daemon for an alternative)

Firewall

  • Rate limit access to a back-end server (either bandwidth or request)
  • Allow/block origin (using authentication)

Crypto-Economics

  • Any service charging for content access (in addition to gas cost). DTP provides generic per byte and/or per request escrow service (to meter pre-agreed cost, limit and quantity... not quality).
  • Pre-paid subscription per day/month (epoch driven?).
  • Various escrow service that allows to shift the transport cost completely at the origin or destination (gas always paid by sender, but escrow service handles fair refund).

Public Broadcasting

  • Allow live broadcasting to automatically turn on/off upon enough fund contributed (thus saving the producer from any expense when no-one is listening).
  • Public broadcast performed upon enough ticket sold.
  • Tip/Request/Message/Audience participation line attach to a public event channel.
\ No newline at end of file + + + + + + + + + + Use Cases | Decentralized Transport Protocol + + + + + +
Skip to main content

Use Cases


DTP provides networking building blocks that can be applied in many ways.

You will find on this page a few inspiring ideas.

When ready Go to choose your installation setup ....

Which layer do you need to work with?

DTP features are available in roughly 3 layers (by increasing level of difficulty):

  • DTP Services Daemon Similar to NGINX, Cloudflare, HAProxy... These are for proxy/forward/firewall services. You will simply be configuring how your data flows between your apps and servers. Your existing apps just use standard TCP/IP sockets (e.g. "localhost:port" URL) to interface with the DTP services daemon.

  • DTP Protocols Think "TCP". The DTP/Sui SDKs allows developers to have more control for connecting any mix of web2 apps (webapp, client/servers...). You will need to write Rust and/or Typescript apps. This is also the solution to eliminate having to install the DTP Services Daemon on your end-users' devices.

  • DTP Sui Move Packages Innovations particular to Sui, such as RPC escrows, data streaming, coins&call equivocation mitigation, metering etc... you will likely be deeply involve into web3 development at this point.

For most users, you will deal only with the "easiest" layer, the "DTP Services Daemon".

If not sure how to proceed for your specific need, then please open a discussion on Discordopen in new window.

Examples/Ideas

Client/Server

  • Web3 frontends connecting to a centralized JSON-RPC backend (More info)
  • Rust/Typescript Web3 Client to centralized TCP Server (More info)

Encrypted Messaging

  • Add traditional user/password login to a dApp. The goal is to allow access to the same "user account" even if done from a different wallet (client address). Implementation often requires "secret messaging" between a centralized server and the Web3 apps.
  • Any user-to-user data transfer
  • Anonymous Tips Line (with potential reward in return).

Networking / Infrastructure

  • Zookeeper, Consul, Serf-like services for discovery and consensus among off-chain servers.
  • UDP, TCP, QUIC/UDP Tunneling: Transport IP protocols packets within a DTP connection for point-to-point applications (See DTP Services Daemon for an alternative)

Firewall

  • Rate limit access to a back-end server (either bandwidth or request)
  • Allow/block origin (using authentication)

Crypto-Economics

  • Any service charging for content access (in addition to gas cost). DTP provides generic per byte and/or per request escrow service (to meter pre-agreed cost, limit and quantity... not quality).
  • Pre-paid subscription per day/month (epoch driven?).
  • Various escrow service that allows to shift the transport cost completely at the origin or destination (gas always paid by sender, but escrow service handles fair refund).

Public Broadcasting

  • Allow live broadcasting to automatically turn on/off upon enough fund contributed (thus saving the producer from any expense when no-one is listening).
  • Public broadcast performed upon enough ticket sold.
  • Tip/Request/Message/Audience participation line attach to a public event channel.
+ + + diff --git a/examples/rpc_firewall.html b/examples/rpc_firewall.html new file mode 100644 index 0000000..e8b3ac0 --- /dev/null +++ b/examples/rpc_firewall.html @@ -0,0 +1,40 @@ + + + + + + + + + + JSON-RPC Firewall | Decentralized Transport Protocol + + + + + +
Skip to main content

JSON-RPC Firewall


JSON-RPC Firewall

In this example, a company want to provide a JSON-RPC API service to its customer front-end applications.

One goal is to protect the web2 server from DDoS attack, in particular, hide the IP address.

A DTP Services Daemon runs as a TCP/IP proxy on the same machine as the web2 server.

Since the sender has to pay for all the data byte transmission costs through the Sui network, an attack is costly and mostly futile.

The server IP address is visible only to the Sui nodes (not to the users on the other side of the Sui network). This mitigates traditional direct IP attacks.

In this example the frontend contact the hidden web2 IP server using the <Host Object ID>:8923 address and DTP takes care of the safe data transfer.

On the drawing, everything in green and blue is provided by DTP and the Sui infrastructure respectively. The application developer provides only what is shown in yellow.

Is the DDoS protection 100% secure?

It depends... the server operator need to have some faith that its Sui node partners are honest (in similar way that one choose to trust a reputable company such as Cloudflare). To mitigate this, a company may choose to run their own Sui fullnodes, making their servers IP addresses near impossible to target by anyone.

Scalability and Reliability

DTP also supports having a single Host Object ID be resolved to more than one backend servers (failover, load-balancing...). This is done through DTP Services configuration.

+ + + diff --git a/examples/web3_rust.html b/examples/web3_rust.html new file mode 100644 index 0000000..07cace8 --- /dev/null +++ b/examples/web3_rust.html @@ -0,0 +1,40 @@ + + + + + + + + + + Web3 Frontend / Rust Server | Decentralized Transport Protocol + + + + + + + + + diff --git a/faq.html b/faq.html new file mode 100644 index 0000000..f648f90 --- /dev/null +++ b/faq.html @@ -0,0 +1,40 @@ + + + + + + + + + + FAQ | Decentralized Transport Protocol + + + + + +
Skip to main content

FAQ


FAQ

In one sentence... What can DTP do?

It is a TCP-Like protocol facilitating data transfer between web2 applications, with additional Web3 features such as services monetization, anonymity and security.

Can DTP be used between Web3 apps?

DTP can selectively connect front-ends WebApp to each other, while keeping the data transfer under the control of a dApps (transit on the Sui network).

As an example, you can use it to allow gamers safely exchange encrypted messages among themselves while they are on the same team in a Web3 game. In this case, DTP provides the WebApp to WebApp connectivity without making the players IP addresses visible.

What sort of data can DTP transport?

Any protocol, any data stream.

Data can be a few bytes for a one time secret exchange for authentication/login. At another extreme, the bandwidth can be for as much as an encrypted video stream (through the innovative combination of DTP Multi-channels and Sui network simple transactions). The economic feasibility of HD video streaming on blockchain is an open question...

Can DTP be used with commercial application?

Yes. DTP is open-source and can freely be used in commercial application (Apache 2.0 License).

How much does it cost to use DTP?

Only the Sui gas needed to run it, expect the execution cost to be mostly driven by the number of bytes transferred.

There is no developer fee or middlemen commission collected for using DTP.

When will DTP have token?

Never.

dApps built on top of DTP can use tokens or charge additional Mist, but this is not within the scope of DTP itself.

Can DTP simply tunnel standard TCP, UDP, IP packets?

Transparent packets tunneling could be done, but it is not recommended.

DTP/Sui provides already reliable and ordered data transport. That would be redundant with say, what TCP would try to achieve within a tunnel.

Instead, look into DTP Services Daemon to efficiently terminate/bridge standard IP protocols. That eliminates protocol redundancy and better leverage what the Sui network already provide.

Any plan to support another blockchain?

No, unless a breakthrough in performance is possible with another blockchain architecture.

Sui provides stable time to finality (low jitter), parallelism and scalability (no contention between connections).

Low jitter allows small and predictable buffer size at the receivers.

Sui simple transactions makes sub-second streaming latency possible.

For now, DTP/Sui might not be well-suited for application that depends on fast sequence of query/response (since that requires two transactions finality). DTP attempts to minimize roundtrips and protocol handshakes at every step.

Where is the code?

DTP still in early design phase and is not yet release. See GitHubopen in new window development branches for "work-in-progress".

Where can I go for more questions?

Try the Discord channel: https://discord.gg/Erb6SwsVbHopen in new window

+ + + diff --git a/faq/index.html b/faq/index.html deleted file mode 100644 index a0cc060..0000000 --- a/faq/index.html +++ /dev/null @@ -1 +0,0 @@ - FAQ - DTP - Decentralized Transport Protocol

FAQ

In one sentence... What can DTP do?

It is a TCP-Like protocol facilitating data streaming between web3 applications and optionaly allow safe access to traditional web2 TCP/IP services using a "smart contract" (DTP).

Can DTP be used between Web3 apps?

Yes.

As an example, you can use it to efficiently let gamers stream data among themselves (P2P).

What sort of data can DTP transport?

Any protocol, any data stream.

Data can be a few bytes for a one time secret exchange for authentication/login. At another extreme, the bandwidth can be for as much as an encrypted video stream (through the innovative combination of DTP Multi-channels and Sui network simple transactions). The economic feasibility of HD video streaming on blockchain is an open question...

Can DTP be used with commercial application?

Yes. DTP is open-source and can freely be used in commercial application (Apache 2.0 License).

How much does it cost to use DTP?

Only the Sui gas needed to run it, expect the execution cost to be mostly driven by the number of bytes transferred.

There is no developer fee or commission collected for using DTP.

When will DTP have token?

Never.

dApps built on top of DTP can use tokens or charge additional Mist, but this is not within the scope of DTP itself.

Can DTP simply tunnel standard TCP, UDP, IP packets?

Transparent packets tunneling could be done, but is not recommended.

DTP/Sui provides already reliable and ordered data transport. That would be redundant with say, what TCP would try to achieve within a tunnel.

Instead, look into DTP Services Daemon to efficiently terminate/bridge standard IP protocols. That eliminates protocol redundancy and better leverage what the Sui network already provide.

Any plan to support another blockchain?

No, unless a breakthrough in performance is possible with another blockchain architecture.

Sui provides stable time to finality (low jitter), parallelism and scalability (no contention between connections).

Low jitter allows small and predictable buffer size at the receivers.

Sui simple transactions makes sub-second streaming latency possible.

For now, DTP/Sui might not be well-suited for application that depends on fast sequence of query/response (since that requires two transactions finality). DTP attempts to minimize roundtrips and protocol handshakes at every step.

Where is the code?

DTP still in early design phase and is not yet release. See GitHub development branches for "work-in-progress".

Where can I go for more questions?

Try the Discord channel: https://discord.gg/Erb6SwsVbH

\ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b411f79ddd958612bceaae08e4fb10ad15340db2 GIT binary patch literal 67646 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 + + + + + + + + + Rust Development Setup Installation | Decentralized Transport Protocol + + + + + +
Skip to main content

Rust Development Setup Installation


Rust Development Setup Installation

Follow the Sui installation

https://docs.sui.io/build/install#prerequisitesopen in new window

Clone DTP

https://github.com/mario4tier/dtpopen in new window

Initialize localnet

Just run the DTP "init-localnet" and it will initialize the whole DTP setup and (re)start the "sui" localnet process as needed.

The localnet will be re-initialized with always the same configuration, address and funding. (it uses its own configuration file at genesis for a deterministic setup).

From this point use "lsui" and "dsui" shell scripts (as a direct replacement of "sui") to access localnet and devnet respectively.

Output example:

~/dtp$ ./dtp/script/init-localnet
+Output location = /home/user/dtp-dev
+Stopping running localnet (sui process pid 1317)
+Building localnet using latest Sui devnet branch...
+    Finished dev [unoptimized + debuginfo] target(s) in 1.29s
+Removing existing /home/user/dtp-dev/localnet directory
+Starting new localnet process (may take up to 30 secs)
+.........
+New localnet started (sui 0.20.0, process pid 6798)
+========
+localnet => http://0.0.0.0:9000 (active)
+devnet => https://fullnode.devnet.sui.io:443
+========
+All addresses with coins:
+Showing 5 results.
+0x267d4904898cbc15f165a18541154ec8c5732fcb
+0x68db58b41d97e4cf1ea7d9327036ebd306a7930a
+0x99d821380348ee02dd685a3af6d7123d92db0d3c
+0xbbd8d0695c369b04e9207fca4ef9f5f15b2c0de7
+0xe7f134729591f52cf0638c2500a7ed228033a9e7
+========
+All coins owned by 0xe7f134729591f52cf0638c2500a7ed228033a9e7 (active):
+                 Object ID                  |  Gas Value
+----------------------------------------------------------------------
+ 0x0b162ef4f83118cc0ad811de35ed330ec3441d7b | 100000000000000
+ 0x2d43245a6af1f65847f7c18d5f6aabbd8e11299b | 100000000000000
+ 0x9811c29f1dadb67aadcd59c75693b4a91b347fbb | 100000000000000
+ 0xc8381677d3c213f9b0e9ef3d2d14051458b6af8a | 100000000000000
+ 0xd0b2b2227244707bce233d13bf537af7a6710c01 | 100000000000000
+========
+
+Remember:
+  Use "dsui" to access devnet
+  Use "lsui" to access your localnet
+
+Success. Try it by typing "lsui client gas"
+host:~/$
+

Publish DTP Package (localnet)

~/dtp$ publish-localnet

Run DTP Integration Test (localnet)

~/dtp$ cargo test

When running integration tests, the test setup makes sure a localnet (sui process) and a peer DTP service Daemon (dtp process) simulate interacting with a remote peer.

This allows to automate your own client/server integration test of your own application on a single machine (Just need to make sure to use a different set of object coin, client address and localhost:port. More on this later).

+ + + diff --git a/how-to/index.html b/how-to/index.html new file mode 100644 index 0000000..992edb5 --- /dev/null +++ b/how-to/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + How to | Decentralized Transport Protocol + + + + + + + + + diff --git a/how-to/install.html b/how-to/install.html new file mode 100644 index 0000000..6c52d6d --- /dev/null +++ b/how-to/install.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + +
Skip to main content


There are 3 ways to install DTP.

Choose the one that best fits your needs and you can always later switch from one to the other.

Choice 1 of 3: Full Development Setup

This is the only setup available for now.

Recommended if you need any of these:

  • Develop Sui Move package (with or without DTP)

  • Create your own Rust application using DTP and/or Sui Rust SDK.

  • Development of a new DTP service (e.g. you are writing your own backend Rust servers and do not want to use the DTP Services daemon as an intermediate).

The setup includes a Sui development framework (Suibase), the DTP Service Daemon runtime, all the DTP SDKs and some utility scripts for quicker edit/publish/debug development cycles.

DTP dev framework is not conflicting with other Sui installations (e.g. official Mysten Labs cargo install) and can be uninstalled easily.

Go to Full Setup ...

Choice 2 of 3: DTP Services Runtime (No Coding)

Not yet implemented

For now, use the Full Development setup, which includes the DTP Services runtime.

Choose this setup if you only need one or more of the following feature:

  • Make your existing server API accessible on the Sui network (e.g. REST, JSON-RPC etc...)

  • Make a local directory content accessible on the Sui network (be a "file server")

  • Allow other user on the network to discover and ping your server.

  • Have end-users (e.g. frontend app) install their own DTP runtime as a local proxy to your backend services.

This setup does not require any coding skills, just configuration in a text file and using the dtp command line tool.

Choice 3 of 3: DTP Typescript SDK (NPM Packages Only)

Not yet implemented

The DTP Typescript SDK is not yet written. Priority is to develop the Rust SDK first.

Choose this setup if you only need to develop front-end apps doing DTP connections to existing services and not require the DTP service daemon installation.

+ + + diff --git a/how-to/npm_only.html b/how-to/npm_only.html new file mode 100644 index 0000000..8bec65c --- /dev/null +++ b/how-to/npm_only.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/how-to/runtime_only.html b/how-to/runtime_only.html new file mode 100644 index 0000000..d360581 --- /dev/null +++ b/how-to/runtime_only.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/index.html b/index.html index c88d8bd..7d468d0 100644 --- a/index.html +++ b/index.html @@ -1 +1,43 @@ - DTP - Decentralized Transport Protocol

For when you want some web2 on the web3 playground

  • Create hybrid dApps


    Decentralized connection control, metering and crypto-economics
               +
    Your existing off-chain service and data.

  • 🛡 Security & DDoS Protection


    • Scalable firewall built-in the Sui network!
    • Stop DDoS attacks even before it reaches your servers.
    • Keep your Web2 servers IP hidden (visible only to Sui node operators).

    See firewall example...

  • Privacy & Authenticity


    • On-chain secret exchanges. DTP always encrypt end-to-end.
    • Secured key/certificate installation on web3 apps from centralized servers.
    • Authenticity with signed data transfer.
  • 🆓 Open-Source


    • Only code from developers for developers. No gimmick.
    • No Token, middlemen, commission or dev fee.
    • Only requires the smart contracts execution costs (the gas for the Sui Move calls).

    Check the FAQ...

  • High Availability


    • Automatic failover and/or load balancing among your backend servers.

    • Maybe your service would benefit from the censorship resistance of the Sui network?

    • Develop Serf-like coordination with a group of other loosely coupled web2 servers.

  • Safe and Fair Hybrid Escrow


    • Add fair Tokenomics to Web2: Pay per request, per byte, per RPC call etc...

    • DTP has built-in "Response Fee Escrow" to prevent query requesters to perform financial attacks against a company/server.

Image title


Image title

Why Sui and not blockchain 'x' ?
SUI has good finality latency stability (low jitter) and network scalability (maintains per connectin throughput regardless of total load).

Sui architecture provides two type of transactions:

  • Simple Transaction with sub-second finality for data plane transfer (See "partial ordering" illustration). This allows fast async/parallel transmission.

  • Narwhal/Bullshark consensus with 2-3 seconds finality used for slower control plane synchronization, like escrow services, reconfiguration, connection creation,etc...

With its dual-type of transactions with the proper set of qualities, Sui makes practical the implementation of common data + control plane design found in IP networks ( Cloudflare explains it well ).

See How Sui Differs from Other Blockchains?

Why not simply use the good old, faster and free internet?

Join the Discord community and let's talk about it!

\ No newline at end of file + + + + + + + + + + Home | Decentralized Transport Protocol + + + + + +
Skip to main content

Why Sui and not blockchain 'x' ?
SUI has good finality latency stability (low jitter) and network scalability (maintains per connection throughput regardless of total load).

Sui architecture provides two type of transactions:

  • Simple Transaction with sub-second finality for data plane transfer (See 'partial ordering' illustration). This allows fast async/parallel transmission.

  • Narwhal/Bullshark consensus with 2-3 seconds finality used for slower control plane synchronization, like escrow services, reconfiguration, connection creation,etc...

With its flexible dual-type of transactions, Sui makes practical the implementation of common data + control plane design found in IP networks ( Cloudflare explains it wellopen in new window ).

See How Sui Differs from Other Blockchains?open in new window

Why not simply use the good old, faster and free internet?

Join the Discord communityopen in new window and let's talk about it!

+ + + diff --git a/intro.html b/intro.html new file mode 100644 index 0000000..8c13439 --- /dev/null +++ b/intro.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + +
Skip to main content


What is DTP?

It is a TCP-Like protocol facilitating data transfer between any web2 applications, with additional Web3 features such as services monetization, anonymity and security.

DTP facilitate high-level data transfer, such as audio, video, RPC calls etc...

DTP can be integrated into your own Rust/Typescript apps (frontend and/or backend).

Alternatively, you can direct your TCP/IP socket (or websocket) traffic toward a local DTP Services daemon. This daemon takes care of adding Web3 capabilities to your existing Web2 traffic (e.g. handles "per request" micro-payments).

Not sure if a good fit? Check a few use cases.

Ready to try it ? Go to Installation.

+ + + diff --git a/assets/logo.png b/logo.png old mode 100644 new mode 100755 similarity index 100% rename from assets/logo.png rename to logo.png diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..364d184 --- /dev/null +++ b/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/overrides/partials/disable_copyright.html b/overrides/partials/disable_copyright.html deleted file mode 100644 index e69de29..0000000 diff --git a/ref/api/index.html b/ref/api/index.html deleted file mode 100644 index b852fc4..0000000 --- a/ref/api/index.html +++ /dev/null @@ -1 +0,0 @@ - Overview - DTP - Decentralized Transport Protocol

Overview

\ No newline at end of file diff --git a/ref/api_rust.html b/ref/api_rust.html new file mode 100644 index 0000000..9c6b1a1 --- /dev/null +++ b/ref/api_rust.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/ref/api_rust/index.html b/ref/api_rust/index.html deleted file mode 100644 index d2c9e38..0000000 --- a/ref/api_rust/index.html +++ /dev/null @@ -1 +0,0 @@ - Rust API - DTP - Decentralized Transport Protocol

Rust API

\ No newline at end of file diff --git a/ref/api_typescript.html b/ref/api_typescript.html new file mode 100644 index 0000000..48438f5 --- /dev/null +++ b/ref/api_typescript.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/ref/api_typescript/index.html b/ref/api_typescript/index.html deleted file mode 100644 index a4f3c62..0000000 --- a/ref/api_typescript/index.html +++ /dev/null @@ -1 +0,0 @@ - Typescript API - DTP - Decentralized Transport Protocol

Typescript API

\ No newline at end of file diff --git a/ref/design.html b/ref/design.html new file mode 100644 index 0000000..7f2e8b3 --- /dev/null +++ b/ref/design.html @@ -0,0 +1,40 @@ + + + + + + + + + + Design | Decentralized Transport Protocol + + + + + +
Skip to main content

Design


Target Audience

Developers should first read the API they intend to use.

This document is for developers curious about DTP inner works.

At high level, how is the Sui Network used?

Sui owned objects are used for unidirectional data transfer with sub-second latency (See Simple Transactionopen in new window in Sui docs).

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data "exit" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be "observed" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most "control plane" synchronizations.

DTP Glossary

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

Objects: Usually refer to Sui objects (See Sui Docsopen in new window)

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be "sent data can be deleted from network storage after 48 hours (2 epochs)". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

Firewall

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

Multi-Channel Connection

Media byte streams are ineviteably divided into transaction "block" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

Some estimations (See on Google Sheetopen in new window):

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

High-Availability and Load Balancing

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should "pull it".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

Uni-directional Transfer

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

Public Broadcasting

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic "on air" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).

There are also some technical challenges particular to broadcasting (See Future Work).

+ + + diff --git a/ref/design/index.html b/ref/design/index.html deleted file mode 100644 index b6c7ddd..0000000 --- a/ref/design/index.html +++ /dev/null @@ -1 +0,0 @@ - Sui Move Objects - DTP - Decentralized Transport Protocol

Sui Move Objects

Target Audience

Developers should first read the API they intend to use.

This document is for developers curious about DTP inner works.

At high level, how is the Sui Network used?

Sui owned objects are used for unidirectional data transfer with sub-second latency (See Simple Transaction in Sui docs).

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data "exit" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be "observed" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most "control plane" synchronizations.

DTP Glossary

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

Objects: Usually refer to Sui objects (See Sui Docs)

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be "sent data can be deleted from network storage after 48 hours (2 epochs)". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

Firewall

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

Multi-Channel Connection

Media byte streams are ineviteably divided into transaction "block" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

Some estimations (See on Google Sheet):

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

High-Availability and Load Balancing

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should "pull it".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

Uni-directional Transfer

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

Public Broadcasting

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic "on air" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).

There are also some technical challenges particular to broadcasting (See Future Work).

\ No newline at end of file diff --git a/ref/future_work.html b/ref/future_work.html new file mode 100644 index 0000000..23ff299 --- /dev/null +++ b/ref/future_work.html @@ -0,0 +1,40 @@ + + + + + + + + + + Future Work | Decentralized Transport Protocol + + + + + +
Skip to main content

Future Work


Future Work

Broadcasting Challenges

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

Data Deletion

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee --> Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

Data Consumption Confirmation

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

Encrypted Broadcasting

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services[^1]), but this is challenging and piracy can (at best) only be mitigated[^2].

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

[^1]: Wikipedia Broadcast Encryptionopen in new window

[^2]: Wikipedia Multicast Encryptionopen in new window

+ + + diff --git a/ref/future_work/index.html b/ref/future_work/index.html deleted file mode 100644 index 9946bba..0000000 --- a/ref/future_work/index.html +++ /dev/null @@ -1 +0,0 @@ - Future works - DTP - Decentralized Transport Protocol

Future Work

Broadcasting Challenges

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

Data Deletion

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee → Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

Data Consumption Confirmation

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

Encrypted Broadcasting

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services1), but this is challenging and piracy can (at best) only be mitigated2.

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

\ No newline at end of file diff --git a/ref/index.html b/ref/index.html new file mode 100644 index 0000000..f491609 --- /dev/null +++ b/ref/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + Basic Concept | Decentralized Transport Protocol + + + + + +
Skip to main content

Basic Concept


Exchange of data through the SUI network can be done between any Web2 application that includes the DTP and Sui SDKs.

Alternatively, the end-users may install the DTP services daemon to handle common cases (e.g making one side of the connection be a JSON-RPC server).

An end-user will first want to establish its own "unique contact point" on the network by creating a "Host Sui Object" using the DTP API.

Note: Most operation done through the DTP API can also be done on the command line with the "dtp" script.

An application can "ping" or "connect" to other Host object created by other apps. Each Host are uniquely identified by a <Host Object ID>.

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

On-Chain Firewall

For security reason, each Host Object are by default created "completely closed". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

Service Level Agreements (SLA)

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a "Service Level Agreement" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of "Typical" service level agreement to help minimize market confusion.

Service Level AgreementWho Pays
OpenDataStreamEveryone pay for their own transactions (txns).
AudioStream-FreeBroadcaster only.
JSON-RPC-BestEffortEveryone pay for their own txns. No response guaranteed.
JSON-RPC-RequesterPaidRPC Requester pays. Responder refunded through escrow.
Ping-RequesterPaidRPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

+ + + diff --git a/ref/readme/index.html b/ref/readme/index.html deleted file mode 100644 index 8174529..0000000 --- a/ref/readme/index.html +++ /dev/null @@ -1 +0,0 @@ - Read Me First - DTP - Decentralized Transport Protocol

Read Me First

Basic Concept

Exchange of data through the SUI network can be done between any Web2 or Web3 application that includes the DTP and Sui SDKs.

An application will first want to create its own "unique contact point" on the network by creating a "Host Sui Object" using the DTP API.

An application can "ping" or "connect" to other Host object created by other apps. Each Host are uniquely identified by a "Sui Object ID".

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

On-Chain Firewall

For security reason, each Host Object are by default created "completely closed". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

Connection Type and Escrow

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a "Service Level Agreement" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of "Typical" service level agreement to help minimize market confusion.

Service Level Agreement Who Pays
OpenDataStream Everyone pay for their own transactions (txns).
AudioStream-Free Broadcaster only.
JSON-RPC-BestEffort Everyone pay for their own txns. No response guaranteed.
JSON-RPC-RequesterPaid RPC Requester pays. Responder refunded through escrow.
Ping-RequesterPaid RPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

\ No newline at end of file diff --git a/ref/scripts.html b/ref/scripts.html new file mode 100644 index 0000000..cf03daf --- /dev/null +++ b/ref/scripts.html @@ -0,0 +1,40 @@ + + + + + + + + + + Decentralized Transport Protocol + + + + + + + + + diff --git a/ref/scripts/index.html b/ref/scripts/index.html deleted file mode 100644 index 35d355a..0000000 --- a/ref/scripts/index.html +++ /dev/null @@ -1 +0,0 @@ - DTP Scripts - DTP - Decentralized Transport Protocol

DTP Scripts

\ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..7e37053 --- /dev/null +++ b/robots.txt @@ -0,0 +1,5 @@ + +User-agent:* +Disallow: + +Sitemap: https://dtp.dev/sitemap.xml diff --git a/search/search_index.json b/search/search_index.json deleted file mode 100644 index 4fca487..0000000 --- a/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Home","text":"For when you want some web2 on the web3 playground
  • Create hybrid dApps

    Decentralized connection control, metering and crypto-economics \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+ Your existing off-chain service and data.

  • Security & DDoS Protection

    • Scalable firewall built-in the Sui network!
    • Stop DDoS attacks even before it reaches your servers.
    • Keep your Web2 servers IP hidden (visible only to Sui node operators).

    See firewall example...

  • Privacy & Authenticity

    • On-chain secret exchanges. DTP always encrypt end-to-end.
    • Secured key/certificate installation on web3 apps from centralized servers.
    • Authenticity with signed data transfer.
  • Open-Source

    • Only code from developers for developers. No gimmick.
    • No Token, middlemen, commission or dev fee.
    • Only requires the smart contracts execution costs (the gas for the Sui Move calls).

    Check the FAQ...

  • High Availability

    • Automatic failover and/or load balancing among your backend servers.

    • Maybe your service would benefit from the censorship resistance of the Sui network?

    • Develop Serf-like coordination with a group of other loosely coupled web2 servers.

  • Safe and Fair Hybrid Escrow

    • Add fair Tokenomics to Web2: Pay per request, per byte, per RPC call etc...

    • DTP has built-in \"Response Fee Escrow\" to prevent query requesters to perform financial attacks against a company/server.

Why Sui and not blockchain 'x' ? SUI has good finality latency stability (low jitter) and network scalability (maintains per connectin throughput regardless of total load).

Sui architecture provides two type of transactions:

  • Simple Transaction with sub-second finality for data plane transfer (See \"partial ordering\" illustration). This allows fast async/parallel transmission.

  • Narwhal/Bullshark consensus with 2-3 seconds finality used for slower control plane synchronization, like escrow services, reconfiguration, connection creation,etc...

With its dual-type of transactions with the proper set of qualities, Sui makes practical the implementation of common data + control plane design found in IP networks ( Cloudflare explains it well ).

See How Sui Differs from Other Blockchains?

Why not simply use the good old, faster and free internet?

Join the Discord community and let's talk about it!

"},{"location":"community/","title":"DTP Community","text":"

Discord Invite: https://discord.gg/Erb6SwsVbH

Mario Fortier - Lead Developer

  • LinkedIn: https://www.linkedin.com/in/mfortier/
  • Discord username : Mhax#6164
  • Github username : https://github.com/mario4tier

(Join, contribute and have your name added here...)

"},{"location":"examples/","title":"Applications Example","text":"

DTP provides networking building blocks that can be applied in many ways.

You will find on this page a few inspiring ideas.

DTP features are made available in roughly 3 layers (in increasing level of difficulty):

  • DTP Services Daemon Similar to NGINX/Cloudflare/HAProxy. These are for proxy/forward/firewall services. You will simply be configuring how your data flows between your apps and hosts.

  • DTP Protocols Think \"TCP\". The DTP/Sui SDKs allows developers to create connections between web2 and web3 apps. You will need to write Rust and/or Typescript apps.

  • DTP Sui Move Packages Innovations particular to Sui, such as RPC escrows, data streaming, coins&call equivocation mitigation, metering etc... you will likely be deeply involve into web3 development at this point.

For most users, you will deal only with the \"easiest\" layer, the \"DTP Services Daemon\".

If not sure how to proceed for your specific need, then please open a discussion on Discord.

When ready Go to choose your installation setup ....

Client/Server

  • Web3 frontends connecting to a centralized JSON-RPC backend (More info)
  • Rust/Typescript Web3 Client to centralized TCP Server (More info)

Encrypted Messaging

  • Add traditional user/password login to a dApp. The goal is to allow access to the same \"user account\" even if done from a different wallet (client address). Implementation often requires \"secret messaging\" between a centralized server and the Web3 apps.
  • Any user-to-user data transfer
  • Anonymous Tips Line (with potential reward in return).

Networking / Infrastructure

  • Zookeeper, Consul, Serf-like services for discovery and consensus among off-chain servers.
  • UDP, TCP, QUIC/UDP Tunneling: Transport IP protocols packets within a DTP connection for point-to-point applications (See DTP Services Daemon for an alternative)

Firewall

  • Rate limit access to a back-end server (either bandwidth or request)
  • Allow/block origin (using authentication)

Crypto-Economics

  • Any service charging for content access (in addition to gas cost). DTP provides generic per byte and/or per request escrow service (to meter pre-agreed cost, limit and quantity... not quality).
  • Pre-paid subscription per day/month (epoch driven?).
  • Various escrow service that allows to shift the transport cost completely at the origin or destination (gas always paid by sender, but escrow service handles fair refund).

Public Broadcasting

  • Allow live broadcasting to automatically turn on/off upon enough fund contributed (thus saving the producer from any expense when no-one is listening).
  • Public broadcast performed upon enough ticket sold.
  • Tip/Request/Message/Audience participation line attach to a public event channel.
"},{"location":"faq/","title":"FAQ","text":"

In one sentence... What can DTP do?

It is a TCP-Like protocol facilitating data streaming between web3 applications and optionaly allow safe access to traditional web2 TCP/IP services using a \"smart contract\" (DTP).

Can DTP be used between Web3 apps?

Yes.

As an example, you can use it to efficiently let gamers stream data among themselves (P2P).

What sort of data can DTP transport?

Any protocol, any data stream.

Data can be a few bytes for a one time secret exchange for authentication/login. At another extreme, the bandwidth can be for as much as an encrypted video stream (through the innovative combination of DTP Multi-channels and Sui network simple transactions). The economic feasibility of HD video streaming on blockchain is an open question...

Can DTP be used with commercial application?

Yes. DTP is open-source and can freely be used in commercial application (Apache 2.0 License).

How much does it cost to use DTP?

Only the Sui gas needed to run it, expect the execution cost to be mostly driven by the number of bytes transferred.

There is no developer fee or commission collected for using DTP.

When will DTP have token?

Never.

dApps built on top of DTP can use tokens or charge additional Mist, but this is not within the scope of DTP itself.

Can DTP simply tunnel standard TCP, UDP, IP packets?

Transparent packets tunneling could be done, but is not recommended.

DTP/Sui provides already reliable and ordered data transport. That would be redundant with say, what TCP would try to achieve within a tunnel.

Instead, look into DTP Services Daemon to efficiently terminate/bridge standard IP protocols. That eliminates protocol redundancy and better leverage what the Sui network already provide.

Any plan to support another blockchain?

No, unless a breakthrough in performance is possible with another blockchain architecture.

Sui provides stable time to finality (low jitter), parallelism and scalability (no contention between connections).

Low jitter allows small and predictable buffer size at the receivers.

Sui simple transactions makes sub-second streaming latency possible.

For now, DTP/Sui might not be well-suited for application that depends on fast sequence of query/response (since that requires two transactions finality). DTP attempts to minimize roundtrips and protocol handshakes at every step.

Where is the code?

DTP still in early design phase and is not yet release. See GitHub development branches for \"work-in-progress\".

Where can I go for more questions?

Try the Discord channel: https://discord.gg/Erb6SwsVbH

"},{"location":"example/rpc_firewall/","title":"JSON-RPC Firewall","text":"

In this example, a Web3 application access a Web2 server providing a JSON-RPC API to its customer.

One of the goal is to protect the Web2 server from DDoS attack, in particular, hide its IP address.

A DTP \"Services Daemon\" runs as a TCP/IP proxy on the same machine as the web2 server.

Since the sender has to pay for all the data byte transmission costs through the Sui network, an attack is costly and mostly futile.

The server IP address is visible only to the Sui nodes (not to the Web3 users on the other side of the Sui network). This mitigates direct traditional IP attacks. The server is not completely hidden, but the owner can control its Sui node partners (in similar way that one choose to, say, trust a reputable company such as Cloudflare).

On the drawing, everything in green and blue is provided by DTP and the Sui infrastructure respectively. The application developer provides only what is shown in yellow.

In this example the Web3 app contact the hidden web2 IP server using the <Host Object ID>:8923 address and DTP takes care of the safe data transfer.

Work-In-Progress... there is more to it... such as mitigation with dynamic <Host ObjectID> to more than one origin IP mapping

"},{"location":"example/web3_rust/","title":"Web3 Client / Rust Server","text":"

Connect any frontend to both a centralized and decentralized backend.

Incomplete Documentation - Work-In-Progress

"},{"location":"ref/design/","title":"Sui Move Objects","text":""},{"location":"ref/design/#target-audience","title":"Target Audience","text":"

Developers should first read the API they intend to use.

This document is for developers curious about DTP inner works.

"},{"location":"ref/design/#at-high-level-how-is-the-sui-network-used","title":"At high level, how is the Sui Network used?","text":"

Sui owned objects are used for unidirectional data transfer with sub-second latency (See Simple Transaction in Sui docs).

Data Ingress: A data stream is sliced into transactions (txns) and added to the Sui network. The txns are targeted to a destination Pipe (owned object).

Data egress: The data \"exit\" the network through event streams (emitted by the txns being received at the destination Pipe). The transmitted data can be \"observed\" by any users, but decoded only by the ones having the decryption key.

The receiving end DTP SDK re-assembles the txns into the original data stream. The stream is then forwarded to the intended end-user (a TCP server, a Rust application layer above etc...).

Slower transactions (Sui consensus) are used for most \"control plane\" synchronizations.

"},{"location":"ref/design/#dtp-glossary","title":"DTP Glossary","text":"

Client: An application that initiate a connection.

Connection: One connection allows exchanging data between two applications. The applications are localized by their Host object on the Sui network. A connection will start to exchange data only after a Transport Control and one or two Pipe objects are created (for uni or bidirectional transfer respectively).

Host Object: Any signature authority that want to transfer data must create its own Host object. This is a Sui shared object involved in many control plane transactions (e.g. creation of a connection). It allows to configure the services (and SLA) that are to be provided, the lifecycle of its associated connections and control the firewall.

Objects: Usually refer to Sui objects (See Sui Docs)

Pipe Object:All off-chain data exchange involves an intermediate object on the Sui network. This object is the Pipe. It is owned by the sender of the data, and have its event stream observed by the receiver(s). A Pipe is loosely coupled to a Transport or Broadcast Control object for synchronization.

Server: Off-chain process intended to respond to client requests.

Service Level Agreement (SLA): Specify the costs, limitations and some behaviors for a service provided by a Host object. Example would be \"sent data can be deleted from network storage after 48 hours (2 epochs)\". The client signifies that it agrees to an SLA at the time the connection to the node is initiated. The SLA specs are such that DTP can enforce the agreement fairly to all parties.

Transport Control Object: Variables and state machines that exists for the lifetime of a single connection. This is a Sui shared object.

"},{"location":"ref/design/#firewall","title":"Firewall","text":"

(1) Gas cost of processing incoming traffic is paid by the sender. That includes connection creation cost and running the firewall at the Pipe Object. Most abuse can therefore be neutralized without requiring any processing/cost from the Server.

Firewall functionality also includes back pressure management to minimize initiating/paying for transactions while the server is already known offline or too busy.

(2) Optionally, the DTP Node Host object gather statistics from all its Pipe objects and adjust the rate limiting rules. This may happen when the Server detects excessive incoming traffic. The gas cost for these likely rare adjustments is to be handled by the Server. (Note: This is a logical representation. More details will follow on how this is implemented such that Pipe objects are not involved with slower consensus transactions).

(3) The server configure the firewall and does a periodical heartbeat using its shared DTP Host object. The server may also do some fast detection and control on the firewall (TBD).

(4) When a transaction has no-effect because of the firewall, there is no event emitted (and sender is informed that the transaction was executed, but blocked by the firewall). Therefore, the Server is not impacted.

"},{"location":"ref/design/#multi-channel-connection","title":"Multi-Channel Connection","text":"

Media byte streams are ineviteably divided into transaction \"block\" at some point. Even with a fast finality, the bandwidth is limited by the maximum transaction size and their serialization as allowed by the L1 network (e.g. one simple transaction per object and gas coin at the time).

Therefore, to support high bandwidth, it might be needed to perform multiple transaction in parallel for a single connection transfer. These transaction flows through independent DTP channels.

Most of the complexity is handled off-chain by DTP when dividing and re-assembling the transactions into a data stream:

Will this be practical? There is a lot of cost/performance unknowns with both Sui network and DTP that will probably persist through 2023. DTP architecture supports media streaming, but it remains to be seen how practical it will be.

Gas might be expensive and there is some potential limitations about how much Sui fullnodes could scale on a viral broadcast (problem at egress of the network, not with the consensus performance itself).

Light data streaming (<20 Kbps) very likely to be supported and be useful within 2023.

Regardless of practicality, support for multi-channel will be at least useful for demo/stress load on a test network.

Some estimations (See on Google Sheet):

(Note: Numbers are best guess as of 11/21/22. Will be revised from time to time)

"},{"location":"ref/design/#high-availability-and-load-balancing","title":"High-Availability and Load Balancing","text":"

Forwarding decision made by Pipe object when multiple end-points (servers)

Off-chain servers can share the incoming load or be each other's fallback for high-availability.

Unlike traditional network, the data is not physically pushed toward a server. Instead, the data remains on the network and an event is emitted about who should \"pull it\".

It is an off-chain responsibility for the application to subscribe to their respective event stream (with proper identifier filtering) and normally retrieve only its assigned data (this change in some recovery scenario).

Configuration of the end-points and health of the servers is managed through the DTP node, which in turn updates all its pipes and transport control objects.

DTP will hide the high complexity of many race conditions (assignment to a server that died) and connection migrations among all end-points belonging to the same Node.

"},{"location":"ref/design/#uni-directional-transfer","title":"Uni-directional Transfer","text":"

Similar to bi-directionals, but with a single Pipe object for data plane to minimize cost/complexity. Control plane still bi-directional (e.g. for encryption handshake).

Uni-Directional Data Transfer

"},{"location":"ref/design/#public-broadcasting","title":"Public Broadcasting","text":"

Similar to unidirectional, but without encryption and using Broadcast objects instead of a Pipe&Transport control.

Broadcasting Specific Objects

Broadcasters may require some different crypto-economic capability. Examples:

  • A live broadcast is wasteful if there is no one listening... one option will be to let DTP stop stream until there are enough fund from listeners to cover, say, the production cost of the next 1 minute. DTP would handle the automatic \"on air\" logic and fairly spread the cost among the contributors.
  • Listener may choose to tip a live broadcaster (for special requests?).

There are also some technical challenges particular to broadcasting (See Future Work).

"},{"location":"ref/future_work/","title":"Future Work","text":""},{"location":"ref/future_work/#broadcasting-challenges","title":"Broadcasting Challenges","text":"

Data broadcasting will put pressure on fullnodes WebSocket event streaming services.

Fullnodes may have low economic incentive to support such high bandwidth services.

The architecture should scale to match the audience size.

Consequently, one possible long term solution is for DTP/Sui to provide only the crypto-economic services and then leave the burden of broadcasting to a public peer-to-peer network.

Each peer is running a DTP app for direct connection to the Sui network (for control plane). The complexity of the data plane transiting through a peer-to-peer network should be hidden to the end-users (Peers).

The use of P2P or not remains irrelevant to the broadcaster which always interface directly to the Sui network.

"},{"location":"ref/future_work/#data-deletion","title":"Data Deletion","text":"

Once the data is confirmed consumed by the receiver(s), then it can be deleted on the L1 network to recover some storage fee \u2192 Revisit the design needed here once Sui implements Storage fund.

The sender of the data can opt out from automated deletion and assume the full storage cost.

Automated deletion is controlled by DTP to provide a fair time for the receiver(s) to consume the data and can be fine tuned through the sender service level agreement (SLA).

The SLAs are published by the server (in its Node object) and one is selected by the client at the time of the connection being established.

"},{"location":"ref/future_work/#data-consumption-confirmation","title":"Data Consumption Confirmation","text":"

TCP protocol includes acknowledgment of L4 delivery to the destination, but without guarantee of being consumed by the application (requires additional protocol at layer 7).

DTP layer supports both; a confirmation of the data being available on the L1 network (TCP delivery equivalent) and optional confirmation of the client consuming the data (L7 protocol equivalent).

Example of use would be to integrate in the dApps the verification that the data was persisted off-chain by the destination. There is no verification that the destination is honest, but this would be used in context where it would be in the destination best interest to act honestly.

"},{"location":"ref/future_work/#encrypted-broadcasting","title":"Encrypted Broadcasting","text":"

For now, broadcast are assumed to be always public and non-encrypted.

Allowing encryption may allow alternative economic model (similar to cable and/or streaming subscription services1), but this is challenging and piracy can (at best) only be mitigated2.

Only the user with the decryption key would be able to make sense of the data. More research to be done about how DTP could implement this feature.

  1. Wikipedia Broadcast Encryption \u21a9

  2. Wikipedia Multicast Encryption \u21a9

"},{"location":"ref/readme/","title":"Read Me First","text":""},{"location":"ref/readme/#basic-concept","title":"Basic Concept","text":"

Exchange of data through the SUI network can be done between any Web2 or Web3 application that includes the DTP and Sui SDKs.

An application will first want to create its own \"unique contact point\" on the network by creating a \"Host Sui Object\" using the DTP API.

An application can \"ping\" or \"connect\" to other Host object created by other apps. Each Host are uniquely identified by a \"Sui Object ID\".

The typical <IP address>:<Port> becomes a <Host Object ID>:<Port>

"},{"location":"ref/readme/#on-chain-firewall","title":"On-Chain Firewall","text":"

For security reason, each Host Object are by default created \"completely closed\". Using the DTP API, an application can choose to open ports of its Host object to progressively add services.

Other application will be able to observe what other Host allow/block even before attempting to use their service. Even if an attacker try to use a service when they should not, it will be rejected by the DTP Move package on-chain, therefore have no impact on the destination.

The DTP API allows fine grain control of allowance/blocking of particular requester, connection count or bandwidth limit. Configuration are kept and applied 24/7 on-chain.

"},{"location":"ref/readme/#connection-type-and-escrow","title":"Connection Type and Escrow","text":"

DTP provides traditional byte streaming (TCP-Like) connections between Host, but also the simplification of higher level connection, in particular RPC calls.

When configuring a service for your Host, you must choose a \"Service Level Agreement\" that DTP will enforce.

An example is to require the requester to pay for the cost of the response that your server will have to provide.

This is a good example where adding Web3 qualities to an existing Web2 service creates API monetization without requiring huge security/edge infrastructure investments

DTP defines a set of \"Typical\" service level agreement to help minimize market confusion.

Service Level Agreement Who Pays OpenDataStream Everyone pay for their own transactions (txns). AudioStream-Free Broadcaster only. JSON-RPC-BestEffort Everyone pay for their own txns. No response guaranteed. JSON-RPC-RequesterPaid RPC Requester pays. Responder refunded through escrow. Ping-RequesterPaid RPC Requester pays. Responder refunded through escrow.

The requester agree to the SLA upon creation of the connection and is enforced through DTP escrow for the connection duration. DTP handles the fund redistribution fairly with consideration of various success/failure criteria (more refinement will follow in ~2024).

"},{"location":"setup/help/","title":"Which setup?","text":""},{"location":"setup/help/#choice-1-of-3-simplified-dtp-services-deployment","title":"Choice 1 of 3: Simplified DTP Services Deployment","text":"

Choose this setup if you only need one of the following feature:

  • (Optional) Make your server API accessible on the Sui network (e.g. REST, JSON-RPC etc...)

  • (Optional) Make a local directory content accessible on the Sui network (be a \"file server\")

  • (Optional) Allow other user on the network to discover and ping your server.

Work-in-progress. Simplified deployment not yet available. For now, these functionalities are parts of the more complex Rust development setup

"},{"location":"setup/help/#choice-2-of-3-dtp-rust-development-setup","title":"Choice 2 of 3: DTP Rust Development Setup","text":"

Choose this setup if you need any of these:

  • Create a Sui Move package (with or without DTP)

  • Create your own Rust application using DTP and/or Sui Rust SDK.

Includes the Sui framework itself, the DTP Service Daemon and all the DTP scripts to facilitate local and devnet testing. Go to Rust Setup ...

"},{"location":"setup/help/#choice-3-of-3-dtp-typescript-sdk-npm-package","title":"Choice 3 of 3: DTP Typescript SDK (NPM Package)","text":"

Typescript development not yet started. Schedule may depend on community/foundation demand

"},{"location":"setup/rust/","title":"Rust Development Setup Installation","text":""},{"location":"setup/rust/#follow-the-sui-installation","title":"Follow the Sui installation","text":"

https://docs.sui.io/build/install#prerequisites

"},{"location":"setup/rust/#clone-dtp","title":"Clone DTP","text":"

https://github.com/mario4tier/dtp

"},{"location":"setup/rust/#initialize-localnet","title":"Initialize localnet","text":"

Just run the DTP \"init-localnet\" and it will initialize the whole DTP setup and (re)start the \"sui\" localnet process as needed.

The localnet will be re-initialized with always the same configuration, address and funding. (it uses its own configuration file at genesis for a deterministice setup).

From this point use \"lsui\" and \"dsui\" shell scripts (as a direct replacement of \"sui\") to access localnet and devnet respectively.

Output example:

~/dtp$ ./dtp/script/init-localnet\nOutput location = /home/user/dtp-dev\nStopping running localnet (sui process pid 1317)\nBuilding localnet using latest Sui devnet branch...\n    Finished dev [unoptimized + debuginfo] target(s) in 1.29s\nRemoving existing /home/user/dtp-dev/localnet directory\nStarting new localnet process (may take up to 30 secs)\n.........\nNew localnet started (sui 0.20.0, process pid 6798)\n========\nlocalnet => http://0.0.0.0:9000 (active)\ndevnet => https://fullnode.devnet.sui.io:443\n========\nAll addresses with coins:\nShowing 5 results.\n0x267d4904898cbc15f165a18541154ec8c5732fcb\n0x68db58b41d97e4cf1ea7d9327036ebd306a7930a\n0x99d821380348ee02dd685a3af6d7123d92db0d3c\n0xbbd8d0695c369b04e9207fca4ef9f5f15b2c0de7\n0xe7f134729591f52cf0638c2500a7ed228033a9e7\n========\nAll coins owned by 0xe7f134729591f52cf0638c2500a7ed228033a9e7 (active):\n                 Object ID                  |  Gas Value\n----------------------------------------------------------------------\n 0x0b162ef4f83118cc0ad811de35ed330ec3441d7b | 100000000000000\n 0x2d43245a6af1f65847f7c18d5f6aabbd8e11299b | 100000000000000\n 0x9811c29f1dadb67aadcd59c75693b4a91b347fbb | 100000000000000\n 0xc8381677d3c213f9b0e9ef3d2d14051458b6af8a | 100000000000000\n 0xd0b2b2227244707bce233d13bf537af7a6710c01 | 100000000000000\n========\n\nRemember:\n  Use \"dsui\" to access devnet\n  Use \"lsui\" to access your localnet\n\nSuccess. Try it by typing \"lsui client gas\"\nhost:~/$\n

"},{"location":"setup/rust/#publish-dtp-package-localnet","title":"Publish DTP Package (localnet)","text":"

~/dtp$ publish-localnet

"},{"location":"setup/rust/#run-dtp-integration-test-localnet","title":"Run DTP Integration Test (localnet)","text":"

~/dtp$ cargo test

When running integration tests, the test setup makes sure a localnet (sui process) and a peer DTP service Daemon (dtp process) simulate interacting with a remote peer.

This allows to automate your own client/server integration test of your own application on a single machine (Just need to make sure to use a different set of object coin, client address and localhost:port. More on this later).

"}]} \ No newline at end of file diff --git a/setup/help/index.html b/setup/help/index.html deleted file mode 100644 index 2645597..0000000 --- a/setup/help/index.html +++ /dev/null @@ -1 +0,0 @@ - Which setup? - DTP - Decentralized Transport Protocol

Which setup?

Choice 1 of 3: Simplified DTP Services Deployment

Choose this setup if you only need one of the following feature:

  • (Optional) Make your server API accessible on the Sui network (e.g. REST, JSON-RPC etc...)

  • (Optional) Make a local directory content accessible on the Sui network (be a "file server")

  • (Optional) Allow other user on the network to discover and ping your server.

Work-in-progress. Simplified deployment not yet available. For now, these functionalities are parts of the more complex Rust development setup

Choice 2 of 3: DTP Rust Development Setup

Choose this setup if you need any of these:

  • Create a Sui Move package (with or without DTP)

  • Create your own Rust application using DTP and/or Sui Rust SDK.

Includes the Sui framework itself, the DTP Service Daemon and all the DTP scripts to facilitate local and devnet testing. Go to Rust Setup ...

Choice 3 of 3: DTP Typescript SDK (NPM Package)

Typescript development not yet started. Schedule may depend on community/foundation demand

\ No newline at end of file diff --git a/setup/rust/index.html b/setup/rust/index.html deleted file mode 100644 index 021bc59..0000000 --- a/setup/rust/index.html +++ /dev/null @@ -1,38 +0,0 @@ - Rust Setup - DTP - Decentralized Transport Protocol

Rust Development Setup Installation

Follow the Sui installation

https://docs.sui.io/build/install#prerequisites

Clone DTP

https://github.com/mario4tier/dtp

Initialize localnet

Just run the DTP "init-localnet" and it will initialize the whole DTP setup and (re)start the "sui" localnet process as needed.

The localnet will be re-initialized with always the same configuration, address and funding. (it uses its own configuration file at genesis for a deterministice setup).

From this point use "lsui" and "dsui" shell scripts (as a direct replacement of "sui") to access localnet and devnet respectively.

Output example:

~/dtp$ ./dtp/script/init-localnet
-Output location = /home/user/dtp-dev
-Stopping running localnet (sui process pid 1317)
-Building localnet using latest Sui devnet branch...
-    Finished dev [unoptimized + debuginfo] target(s) in 1.29s
-Removing existing /home/user/dtp-dev/localnet directory
-Starting new localnet process (may take up to 30 secs)
-.........
-New localnet started (sui 0.20.0, process pid 6798)
-========
-localnet => http://0.0.0.0:9000 (active)
-devnet => https://fullnode.devnet.sui.io:443
-========
-All addresses with coins:
-Showing 5 results.
-0x267d4904898cbc15f165a18541154ec8c5732fcb
-0x68db58b41d97e4cf1ea7d9327036ebd306a7930a
-0x99d821380348ee02dd685a3af6d7123d92db0d3c
-0xbbd8d0695c369b04e9207fca4ef9f5f15b2c0de7
-0xe7f134729591f52cf0638c2500a7ed228033a9e7
-========
-All coins owned by 0xe7f134729591f52cf0638c2500a7ed228033a9e7 (active):
-                 Object ID                  |  Gas Value
-----------------------------------------------------------------------
- 0x0b162ef4f83118cc0ad811de35ed330ec3441d7b | 100000000000000
- 0x2d43245a6af1f65847f7c18d5f6aabbd8e11299b | 100000000000000
- 0x9811c29f1dadb67aadcd59c75693b4a91b347fbb | 100000000000000
- 0xc8381677d3c213f9b0e9ef3d2d14051458b6af8a | 100000000000000
- 0xd0b2b2227244707bce233d13bf537af7a6710c01 | 100000000000000
-========
-
-Remember:
-  Use "dsui" to access devnet
-  Use "lsui" to access your localnet
-
-Success. Try it by typing "lsui client gas"
-host:~/$
-

Publish DTP Package (localnet)

~/dtp$ publish-localnet

Run DTP Integration Test (localnet)

~/dtp$ cargo test

When running integration tests, the test setup makes sure a localnet (sui process) and a peer DTP service Daemon (dtp process) simulate interacting with a remote peer.

This allows to automate your own client/server integration test of your own application on a single machine (Just need to make sure to use a different set of object coin, client address and localhost:port. More on this later).

\ No newline at end of file diff --git a/setup/services/index.html b/setup/services/index.html deleted file mode 100644 index 9d0df74..0000000 --- a/setup/services/index.html +++ /dev/null @@ -1 +0,0 @@ - Services - DTP - Decentralized Transport Protocol

Services

\ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index d47aeab..d7abc5c 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,83 +1,3 @@ - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - - None - 2023-02-21 - daily - - \ No newline at end of file + +https://dtp.dev/2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/faq.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/intro.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/community/2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/community/editors.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/examples/2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/examples/rpc_firewall.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/examples/web3_rust.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/api_rust.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/api_typescript.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/design.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/future_work.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/docs/scripts.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/how-to/full_setup.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/how-to/install.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/how-to/npm_only.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/how-to/runtime_only.html2024-02-14T03:11:10.000Zdailyhttps://dtp.dev/ref/dailyhttps://dtp.dev/ref/api_rust.htmldailyhttps://dtp.dev/ref/api_typescript.htmldailyhttps://dtp.dev/ref/design.htmldailyhttps://dtp.dev/ref/future_work.htmldailyhttps://dtp.dev/ref/scripts.htmldaily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz deleted file mode 100644 index bcee69640e64f3de543749ae497c0e71464f7fa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206 zcmV;<05Sg`iwFpoRrO;6|8r?{Wo=<_E_iKh0PWVj4#FT12k_meAnXN-iyBHdM<;y% zLa`;GPywyJz4RldyDPVF{JGq3h1KugfS2+?J6pjL5eSr(uFZcyT>@T1OwbYX9Y{4TSh~5Gagtx0RSZwv_CbW$ zyM|Lj_XVK^Ez`)FZN_9LY^&~GJ$NIu`7pdm77_o*jAuOK8P9meGyXR|AL%#1zcO#c IVm$}|0NTx9O#lD@ diff --git a/sitemap.xsl b/sitemap.xsl new file mode 100644 index 0000000..a76881a --- /dev/null +++ b/sitemap.xsl @@ -0,0 +1,207 @@ + + + + + + + XML Sitemap + + + + + +
+

Sitemap

+ + + + + + + + + + + + + + + + + + + + + +
+ + PriorityChange FrequencyLast Updated Time
+ + + + + + + + + + + + + 0.5 + + + + + + + + + - + + + + +
+
+ + + +
+